2 * Copyright (C) 2005-2008 by Daniel Wagner
3 * Copyright (C) 2005-2008 by Pieter Palmers
5 * This file is part of FFADO
6 * FFADO = Free Firewire (pro-)audio drivers for linux
8 * FFADO is based upon FreeBoB
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 2 of the License, or
13 * (at your option) version 3 of the License.
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.
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/>.
28 #include "config_debug.h"
30 #include "../fbtypes.h"
37 #include <semaphore.h>
39 #define FFADO_ASSERT(x) { \
41 m_debugModule.print( DebugModule::eDL_Fatal, \
45 "Assertion failed...\n"); \
46 debugPrintBacktrace( 10 ); \
47 DebugModuleManager::instance()->flush(); \
51 typedef short debug_level_t
;
53 #define DEBUG_LEVEL_MESSAGE 0
54 #define DEBUG_LEVEL_FATAL 1
55 #define DEBUG_LEVEL_ERROR 2
56 #define DEBUG_LEVEL_WARNING 3
57 #define DEBUG_LEVEL_NORMAL 4
58 #define DEBUG_LEVEL_INFO 5
59 #define DEBUG_LEVEL_VERBOSE 6
60 #define DEBUG_LEVEL_VERY_VERBOSE 7
61 #define DEBUG_LEVEL_ULTRA_VERBOSE 8
63 /* MB_NEXT() relies on the fact that MB_BUFFERS is a power of two */
64 #define MB_NEXT(index) (((index)+1) & (DEBUG_MB_BUFFERS-1))
65 #define MB_BUFFERSIZE DEBUG_MAX_MESSAGE_LENGTH
67 // no backtrace support when not debugging
69 #undef DEBUG_BACKTRACE_SUPPORT
70 #define DEBUG_BACKTRACE_SUPPORT 0
73 // no backlog support when not debugging
75 #undef DEBUG_BACKLOG_SUPPORT
76 #define DEBUG_BACKLOG_SUPPORT 0
79 // the backlog is a similar buffer as the message buffer
80 #define DEBUG_BACKLOG_MB_NEXT(index) (((index)+1) & (DEBUG_BACKLOG_MB_BUFFERS-1))
81 #define DEBUG_BACKLOG_MIN_LEVEL DEBUG_LEVEL_VERY_VERBOSE
83 #define debugFatal( format, args... ) \
84 m_debugModule.print( DebugModule::eDL_Fatal, \
90 #define debugError( format, args... ) \
91 m_debugModule.print( DebugModule::eDL_Error, \
97 #define debugWarning( format, args... ) \
98 m_debugModule.print( DebugModule::eDL_Warning, \
105 #define debugFatalShort( format, args... ) \
106 m_debugModule.printShort( DebugModule::eDL_Fatal, \
109 #define debugErrorShort( format, args... ) \
110 m_debugModule.printShort( DebugModule::eDL_Error, \
113 #define debugWarningShort( format, args... ) \
114 m_debugModule.printShort( DebugModule::eDL_Warning, \
118 // these are for messages that are also displayed when not compiled
119 // for debug messages
120 #ifdef DEBUG_KESSAGES
121 #define printMessage( format, args... ) \
122 m_debugModule.print( DebugModule::eDL_Message, \
129 #define printMessage( format, args... ) \
130 m_debugModule.printShort( DebugModule::eDL_Message, \
134 #define printMessageShort( format, args... ) \
135 m_debugModule.printShort( DebugModule::eDL_Message, \
139 #define DECLARE_DEBUG_MODULE static DebugModule m_debugModule
140 #define DECLARE_DEBUG_MODULE_REFERENCE DebugModule &m_debugModule
141 #define IMPL_DEBUG_MODULE( ClassName, RegisterName, Level ) \
142 DebugModule ClassName::m_debugModule = \
143 DebugModule( #RegisterName, Level )
145 #define DECLARE_GLOBAL_DEBUG_MODULE extern DebugModule m_debugModule
146 #define IMPL_GLOBAL_DEBUG_MODULE( RegisterName, Level ) \
147 DebugModule m_debugModule = \
148 DebugModule( #RegisterName, Level )
150 #define setDebugLevel( Level ) { \
151 m_debugModule.setLevel( Level ); \
154 /* m_debugModule.print( eDL_Normal, \
158 "Setting debug level to %d\n", \
162 #define getDebugLevel( ) \
163 m_debugModule.getLevel( )
165 #define flushDebugOutput() DebugModuleManager::instance()->flush()
167 #if DEBUG_BACKLOG_SUPPORT
169 #define debugShowBackLog() \
171 m_debugModule.print( DebugModule::eDL_Warning, \
175 "Backlog print requested\n"); \
176 DebugModuleManager::instance()->showBackLog(); \
178 #define debugShowBackLogLines(x) \
180 m_debugModule.print( DebugModule::eDL_Warning, \
184 "Backlog print requested\n"); \
185 DebugModuleManager::instance()->showBackLog(x); \
189 #define debugShowBackLog()
190 #define debugShowBackLogLines(x)
194 #ifdef DEBUG_MESSAGES
196 #define debugOutput( level, format, args... ) \
197 m_debugModule.print( level, \
204 #define debugOutputShort( level, format, args... ) \
205 m_debugModule.printShort( level, \
208 #define DEBUG_NORMAL( x ) x;
210 #if DEBUG_EXTREME_ENABLE
211 #define debugOutputExtreme( level, format, args... ) \
212 m_debugModule.print( level, \
218 #define debugOutputShortExtreme( level, format, args... ) \
219 m_debugModule.printShort( level, \
222 #define DEBUG_EXTREME( x ) x;
224 #define debugOutputExtreme( level, format, args... )
225 #define debugOutputShortExtreme( level, format, args... )
226 #define DEBUG_EXTREME( x )
231 #define debugOutput( level, format, args... )
232 #define debugOutputShort( level, format, args... )
233 #define DEBUG_NORMAL( x )
235 #define debugOutputExtreme( level, format, args... )
236 #define debugOutputShortExtreme( level, format, args... )
237 #define DEBUG_EXTREME( x )
241 /* Enable preemption checking for Linux Realtime Preemption kernels.
243 * This checks if any RT-safe code section does anything to cause CPU
244 * preemption. Examples are sleep() or other system calls that block.
245 * If a problem is detected, the kernel writes a syslog entry, and
246 * sends SIGUSR2 to the client.
249 // #define DO_PREEMPTION_CHECKING
251 #include <sys/time.h>
253 #ifdef DO_PREEMPTION_CHECKING
254 #define CHECK_PREEMPTION(onoff) \
255 gettimeofday((struct timeval *)1, (struct timezone *)onoff)
257 #define CHECK_PREEMPTION(onoff)
263 #if DEBUG_BACKTRACE_SUPPORT
264 #define debugPrintBacktrace( _SIZE_ ) \
265 DebugModuleManager::instance()->printBacktrace( _SIZE_ );
266 #define debugBacktraceGet( _ID_ ) \
267 DebugModuleManager::instance()->getBacktracePtr( _ID_ );
268 #define debugGetFunctionNameFromAddr( _ADDR_, _BUFF_, _MAX_SIZE_ ) \
269 DebugModuleManager::instance()->getFunctionName( _ADDR_, _BUFF_, _MAX_SIZE_ );
271 #define debugPrintBacktrace( _SIZE_ )
272 #define debugBacktraceGet( _ID_ ) NULL
273 #define debugGetFunctionNameFromAddr( _ADDR_, _BUFF_, _MAX_SIZE_ )
280 unsigned char toAscii( unsigned char c
);
281 void quadlet2char( fb_quadlet_t quadlet
, unsigned char* buff
);
282 void hexDump( unsigned char *data_start
, unsigned int length
);
283 void hexDumpQuadlets( quadlet_t
*data_start
, unsigned int length
);
285 class DebugModuleManager
;
289 friend class DebugModuleManager
;
292 eDL_Message
= DEBUG_LEVEL_MESSAGE
,
293 eDL_Fatal
= DEBUG_LEVEL_FATAL
,
294 eDL_Error
= DEBUG_LEVEL_ERROR
,
295 eDL_Warning
= DEBUG_LEVEL_WARNING
,
296 eDL_Normal
= DEBUG_LEVEL_NORMAL
,
297 eDL_Info
= DEBUG_LEVEL_INFO
,
298 eDL_Verbose
= DEBUG_LEVEL_VERBOSE
,
299 eDL_VeryVerbose
= DEBUG_LEVEL_VERY_VERBOSE
,
300 eDL_UltraVerbose
= DEBUG_LEVEL_ULTRA_VERBOSE
,
303 DebugModule( std::string name
, debug_level_t level
);
304 virtual ~DebugModule();
306 void printShort( debug_level_t level
,
310 __attribute__((format(printf
, 3, 4)))
314 void print( debug_level_t level
,
316 const char* function
,
321 __attribute__((format(printf
, 6, 7)))
325 bool setLevel( debug_level_t level
)
326 { m_level
= level
; return true; }
327 debug_level_t
getLevel()
329 std::string
getName()
333 const char* getPreSequence( debug_level_t level
) const;
334 const char* getPostSequence( debug_level_t level
) const;
338 debug_level_t m_level
;
339 DebugModuleManager
* m_manager
;
343 class DebugModuleManager
{
345 friend class DebugModule
;
347 static DebugModuleManager
* instance();
348 ~DebugModuleManager();
350 bool setMgrDebugLevel( std::string name
, debug_level_t level
);
354 #if DEBUG_BACKLOG_SUPPORT
355 // the backlog is a ringbuffer of all the messages
356 // that have been recorded using the debugPrint
357 // statements, regardless of the debug level.
358 // This is useful to obtain more debug info
359 // when something goes wrong without having too
360 // much output in normal operation
362 void showBackLog(int nblines
);
365 #if DEBUG_BACKTRACE_SUPPORT
366 void printBacktrace(int len
);
367 void *getBacktracePtr(int id
);
368 void getFunctionName( void *, char *, int );
372 bool registerModule( DebugModule
& debugModule
);
373 bool unregisterModule( DebugModule
& debugModule
);
377 void print(const char *msg
);
379 #if DEBUG_BACKLOG_SUPPORT
380 void backlog_print(const char *msg
);
384 DebugModuleManager();
386 typedef std::vector
< DebugModule
* > DebugModuleVector
;
387 typedef std::vector
< DebugModule
* >::iterator DebugModuleVectorIterator
;
389 unsigned int mb_initialized
;
391 #if DEBUG_USE_MESSAGE_BUFFER
392 char mb_buffers
[DEBUG_MB_BUFFERS
][MB_BUFFERSIZE
];
393 unsigned int mb_inbuffer
;
394 unsigned int mb_outbuffer
;
395 unsigned int mb_overruns
;
396 pthread_t mb_writer_thread
;
397 pthread_mutex_t mb_write_lock
;
398 pthread_mutex_t mb_flush_lock
;
402 #if DEBUG_BACKTRACE_SUPPORT
403 pthread_mutex_t m_backtrace_lock
;
404 char m_backtrace_strbuffer
[MB_BUFFERSIZE
];
405 void *m_backtrace_buffer
[DEBUG_MAX_BACKTRACE_LENGTH
];
406 void *m_backtrace_buffer_seen
[DEBUG_MAX_BACKTRACE_FUNCTIONS_SEEN
];
407 int m_backtrace_buffer_nb_seen
;
410 static void *mb_thread_func(void *arg
);
413 #if DEBUG_BACKLOG_SUPPORT
415 char bl_mb_buffers
[DEBUG_BACKLOG_MB_BUFFERS
][MB_BUFFERSIZE
];
416 unsigned int bl_mb_inbuffer
;
417 pthread_mutex_t bl_mb_write_lock
;
420 static DebugModuleManager
* m_instance
;
421 DebugModuleVector m_debugModules
;