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

Revision 776, 10.7 kB (checked in by ppalmers, 16 years ago)

try to fix deadlock / performace issues

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