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

Revision 690, 9.7 kB (checked in by ppalmers, 16 years ago)

some small changes on the backlog:
- locks the flush_lock such that the backlog is not interrupted by normal messages
- allows to specify a minimum level the messages should have to be put in the backlog
- add another level of debugging

  • 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 library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1, as published by the Free Software Foundation;
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22  * MA 02110-1301 USA
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_FATAL          0
37 #define DEBUG_LEVEL_ERROR          1
38 #define DEBUG_LEVEL_WARNING        2
39 #define DEBUG_LEVEL_NORMAL         3
40 #define DEBUG_LEVEL_INFO           4
41 #define DEBUG_LEVEL_VERBOSE        5
42 #define DEBUG_LEVEL_VERY_VERBOSE   6
43 #define DEBUG_LEVEL_ULTRA_VERBOSE  7
44
45 #define DEBUG_MAX_MESSAGE_LENGTH 512
46
47 /* MB_NEXT() relies on the fact that MB_BUFFERS is a power of two */
48 #define MB_BUFFERS          (1<<16)
49
50 #define MB_NEXT(index)      (((index)+1) & (MB_BUFFERS-1))
51
52 #define MB_BUFFERSIZE       DEBUG_MAX_MESSAGE_LENGTH
53
54 // the backlog is a similar buffer as the message buffer
55 #define BACKLOG_MB_BUFFERS      (256)
56 #define BACKLOG_MB_NEXT(index)  (((index)+1) & (BACKLOG_MB_BUFFERS-1))
57 #define BACKLOG_MB_BUFFERSIZE   DEBUG_MAX_MESSAGE_LENGTH
58 #define BACKLOG_MIN_LEVEL       DEBUG_LEVEL_VERY_VERBOSE
59
60
61 #define debugFatal( format, args... )                               \
62                 m_debugModule.print( DebugModule::eDL_Fatal,        \
63                                      __FILE__,                      \
64                                      __FUNCTION__,                  \
65                                      __LINE__,                      \
66                                      format,                        \
67                                      ##args )
68 #define debugError( format, args... )                               \
69                 m_debugModule.print( DebugModule::eDL_Error,        \
70                                      __FILE__,                      \
71                                      __FUNCTION__,                  \
72                                      __LINE__,                      \
73                                      format,                        \
74                                      ##args )
75 #define debugWarning( format, args... )                             \
76                 m_debugModule.print( DebugModule::eDL_Warning,      \
77                                      __FILE__,                      \
78                                      __FUNCTION__,                  \
79                                      __LINE__,                      \
80                                     format,                         \
81                                     ##args )
82
83 #define debugFatalShort( format, args... )                          \
84                 m_debugModule.printShort( DebugModule::eDL_Fatal,   \
85                                      format,                        \
86                                      ##args )
87 #define debugErrorShort( format, args... )                          \
88                 m_debugModule.printShort( DebugModule::eDL_Error,   \
89                                      format,                        \
90                                      ##args )
91 #define debugWarningShort( format, args... )                        \
92                 m_debugModule.printShort( DebugModule::eDL_Warning, \
93                                      format,                        \
94                                      ##args )
95
96 #define DECLARE_DEBUG_MODULE static DebugModule m_debugModule
97 #define IMPL_DEBUG_MODULE( ClassName, RegisterName, Level )        \
98                 DebugModule ClassName::m_debugModule =             \
99                     DebugModule( #RegisterName, Level )
100
101 #define DECLARE_GLOBAL_DEBUG_MODULE extern DebugModule m_debugModule
102 #define IMPL_GLOBAL_DEBUG_MODULE( RegisterName, Level )            \
103                 DebugModule m_debugModule =                        \
104             DebugModule( #RegisterName, Level )
105
106 #define setDebugLevel( Level ) {                                    \
107                 m_debugModule.setLevel( Level ); \
108                 }
109
110 /*                m_debugModule.print( eDL_Normal,                        \
111                                      __FILE__,                     \
112                                      __FUNCTION__,                 \
113                                      __LINE__,                     \
114                                      "Setting debug level to %d\n",  \
115                                      Level ); \
116                 }*/
117
118 #define getDebugLevel(  )                                     \
119                 m_debugModule.getLevel( )
120
121 #define flushDebugOutput()      DebugModuleManager::instance()->flush()
122 #define debugShowBackLog()      DebugModuleManager::instance()->showBackLog()
123
124 #ifdef DEBUG
125
126     #define debugOutput( level, format, args... )                  \
127                 m_debugModule.print( level,                        \
128                                      __FILE__,                     \
129                                      __FUNCTION__,                 \
130                                      __LINE__,                     \
131                                      format,                       \
132                                      ##args )
133
134     #define debugOutputShort( level, format, args... )             \
135                 m_debugModule.printShort( level,                   \
136                                      format,                       \
137                                      ##args )
138
139 #else
140
141     #define debugOutput( level, format, args... )
142     #define debugOutputShort( level, format, args... )
143
144 #endif
145
146 /* Enable preemption checking for Linux Realtime Preemption kernels.
147  *
148  * This checks if any RT-safe code section does anything to cause CPU
149  * preemption.  Examples are sleep() or other system calls that block.
150  * If a problem is detected, the kernel writes a syslog entry, and
151  * sends SIGUSR2 to the client.
152  */
153
154 // #define DO_PREEMPTION_CHECKING
155
156 #include <sys/time.h>
157
158 #ifdef DO_PREEMPTION_CHECKING
159 #define CHECK_PREEMPTION(onoff) \
160     gettimeofday((struct timeval *)1, (struct timezone *)onoff)
161 #else
162 #define CHECK_PREEMPTION(onoff)
163 #endif
164
165 unsigned char toAscii( unsigned char c );
166 void quadlet2char( fb_quadlet_t quadlet, unsigned char* buff );
167 void hexDump( unsigned char *data_start, unsigned int length );
168 void hexDumpQuadlets( quadlet_t *data_start, unsigned int length );
169
170 class DebugModule {
171 public:
172     enum {
173         eDL_Fatal        = DEBUG_LEVEL_FATAL,
174         eDL_Error        = DEBUG_LEVEL_ERROR,
175         eDL_Warning      = DEBUG_LEVEL_WARNING,
176         eDL_Normal       = DEBUG_LEVEL_NORMAL,
177         eDL_Info         = DEBUG_LEVEL_INFO,
178         eDL_Verbose      = DEBUG_LEVEL_VERBOSE,
179         eDL_VeryVerbose  = DEBUG_LEVEL_VERY_VERBOSE,
180         eDL_UltraVerbose = DEBUG_LEVEL_ULTRA_VERBOSE,
181     } EDebugLevel;
182
183     DebugModule( std::string name, debug_level_t level );
184     virtual ~DebugModule();
185
186     void printShort( debug_level_t level,
187                      const char* format,
188                      ... ) const;
189
190     void print( debug_level_t level,
191                 const char*   file,
192                 const char*   function,
193                 unsigned int  line,
194                 const char*   format,
195                 ... ) const;
196
197     bool setLevel( debug_level_t level )
198         { m_level = level; return true; }
199     debug_level_t getLevel()
200         { return m_level; }
201     std::string getName()
202         { return m_name; }
203
204 protected:
205     const char* getPreSequence( debug_level_t level ) const;
206     const char* getPostSequence( debug_level_t level ) const;
207
208 private:
209     std::string   m_name;
210     debug_level_t m_level;
211 };
212
213
214 class DebugModuleManager {
215 public:
216     friend class DebugModule;
217
218     static DebugModuleManager* instance();
219     ~DebugModuleManager();
220
221     bool setMgrDebugLevel( std::string name, debug_level_t level );
222
223     void flush();
224
225     // the backlog is a ringbuffer of all the messages
226     // that have been recorded using the debugPrint
227     // statements, regardless of the debug level.
228     // This is useful to obtain more debug info
229     // when something goes wrong without having too
230     // much output in normal operation
231     void showBackLog();
232
233 protected:
234     bool registerModule( DebugModule& debugModule );
235     bool unregisterModule( DebugModule& debugModule );
236
237     bool init();
238
239     void print(const char *fmt, ...);
240     void va_print(const char *fmt, va_list);
241
242     void backlog_print(const char *fmt, ...);
243     void backlog_va_print(const char *fmt, va_list);
244
245 private:
246     DebugModuleManager();
247
248     typedef std::vector< DebugModule* > DebugModuleVector;
249     typedef std::vector< DebugModule* >::iterator DebugModuleVectorIterator;
250
251     char mb_buffers[MB_BUFFERS][MB_BUFFERSIZE];
252     unsigned int mb_initialized;
253     unsigned int mb_inbuffer;
254     unsigned int mb_outbuffer;
255     unsigned int mb_overruns;
256     pthread_t mb_writer_thread;
257     pthread_mutex_t mb_write_lock;
258     pthread_mutex_t mb_flush_lock;
259     pthread_cond_t mb_ready_cond;
260
261     static void *mb_thread_func(void *arg);
262     void mb_flush();
263
264     // the backlog
265     char bl_mb_buffers[BACKLOG_MB_BUFFERS][BACKLOG_MB_BUFFERSIZE];
266     unsigned int bl_mb_inbuffer;
267     pthread_mutex_t bl_mb_write_lock;
268
269     static DebugModuleManager* m_instance;
270     DebugModuleVector          m_debugModules;
271 };
272
273 #endif
Note: See TracBrowser for help on using the browser.