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

Revision 698, 9.9 kB (checked in by ppalmers, 13 years ago)

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