u_debug.h revision 01e04c3f
1/**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28/**
29 * @file
30 * Cross-platform debugging helpers.
31 *
32 * For now it just has assert and printf replacements, but it might be extended
33 * with stack trace reports and more advanced logging in the near future.
34 *
35 * @author Jose Fonseca <jfonseca@vmware.com>
36 */
37
38#ifndef U_DEBUG_H_
39#define U_DEBUG_H_
40
41
42#include "util/os_misc.h"
43
44#if defined(PIPE_OS_HAIKU)
45/* Haiku provides debug_printf in libroot with OS.h */
46#include <OS.h>
47#endif
48
49#include "pipe/p_defines.h"
50
51
52#ifdef	__cplusplus
53extern "C" {
54#endif
55
56
57#if defined(__GNUC__)
58#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list)))
59#else
60#define _util_printf_format(fmt, list)
61#endif
62
63void _debug_vprintf(const char *format, va_list ap);
64
65
66static inline void
67_debug_printf(const char *format, ...)
68{
69   va_list ap;
70   va_start(ap, format);
71   _debug_vprintf(format, ap);
72   va_end(ap);
73}
74
75
76/**
77 * Print debug messages.
78 *
79 * The actual channel used to output debug message is platform specific. To
80 * avoid misformating or truncation, follow these rules of thumb:
81 * - output whole lines
82 * - avoid outputing large strings (512 bytes is the current maximum length
83 * that is guaranteed to be printed in all platforms)
84 */
85#if !defined(PIPE_OS_HAIKU)
86static inline void
87debug_printf(const char *format, ...) _util_printf_format(1,2);
88
89static inline void
90debug_printf(const char *format, ...)
91{
92#ifdef DEBUG
93   va_list ap;
94   va_start(ap, format);
95   _debug_vprintf(format, ap);
96   va_end(ap);
97#else
98   (void) format; /* silence warning */
99#endif
100}
101#endif
102
103
104/*
105 * ... isn't portable so we need to pass arguments in parentheses.
106 *
107 * usage:
108 *    debug_printf_once(("answer: %i\n", 42));
109 */
110#define debug_printf_once(args) \
111   do { \
112      static boolean once = TRUE; \
113      if (once) { \
114         once = FALSE; \
115         debug_printf args; \
116      } \
117   } while (0)
118
119
120#ifdef DEBUG
121#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
122#else
123#define debug_vprintf(_format, _ap) ((void)0)
124#endif
125
126
127#ifdef DEBUG
128/**
129 * Dump a blob in hex to the same place that debug_printf sends its
130 * messages.
131 */
132void debug_print_blob( const char *name, const void *blob, unsigned size );
133#else
134#define debug_print_blob(_name, _blob, _size) ((void)0)
135#endif
136
137
138/**
139 * Disable interactive error message boxes.
140 *
141 * Should be called as soon as possible for effectiveness.
142 */
143void
144debug_disable_error_message_boxes(void);
145
146
147/**
148 * Hard-coded breakpoint.
149 */
150#ifdef DEBUG
151#define debug_break() os_break()
152#else /* !DEBUG */
153#define debug_break() ((void)0)
154#endif /* !DEBUG */
155
156
157long
158debug_get_num_option(const char *name, long dfault);
159
160#ifdef _MSC_VER
161__declspec(noreturn)
162#endif
163void _debug_assert_fail(const char *expr,
164                        const char *file,
165                        unsigned line,
166                        const char *function)
167#if defined(__GNUC__) && !defined(DEBUG)
168   __attribute__((noreturn))
169#endif
170;
171
172
173/**
174 * Assert macro
175 *
176 * Do not expect that the assert call terminates -- errors must be handled
177 * regardless of assert behavior.
178 *
179 * For non debug builds the assert macro will expand to a no-op, so do not
180 * call functions with side effects in the assert expression.
181 */
182#ifndef NDEBUG
183#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
184#else
185#define debug_assert(expr) (void)(0 && (expr))
186#endif
187
188
189/** Override standard assert macro */
190#ifdef assert
191#undef assert
192#endif
193#define assert(expr) debug_assert(expr)
194
195
196/**
197 * Output the current function name.
198 */
199#ifdef DEBUG
200#define debug_checkpoint() \
201   _debug_printf("%s\n", __FUNCTION__)
202#else
203#define debug_checkpoint() \
204   ((void)0)
205#endif
206
207
208/**
209 * Output the full source code position.
210 */
211#ifdef DEBUG
212#define debug_checkpoint_full() \
213   _debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __FUNCTION__)
214#else
215#define debug_checkpoint_full() \
216   ((void)0)
217#endif
218
219
220/**
221 * Output a warning message. Muted on release version.
222 */
223#ifdef DEBUG
224#define debug_warning(__msg) \
225   _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
226#else
227#define debug_warning(__msg) \
228   ((void)0)
229#endif
230
231
232/**
233 * Emit a warning message, but only once.
234 */
235#ifdef DEBUG
236#define debug_warn_once(__msg) \
237   do { \
238      static bool warned = FALSE; \
239      if (!warned) { \
240         _debug_printf("%s:%u:%s: one time warning: %s\n", \
241                       __FILE__, __LINE__, __FUNCTION__, __msg); \
242         warned = TRUE; \
243      } \
244   } while (0)
245#else
246#define debug_warn_once(__msg) \
247   ((void)0)
248#endif
249
250
251/**
252 * Output an error message. Not muted on release version.
253 */
254#ifdef DEBUG
255#define debug_error(__msg) \
256   _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
257#else
258#define debug_error(__msg) \
259   _debug_printf("error: %s\n", __msg)
260#endif
261
262/**
263 * Output a debug log message to the debug info callback.
264 */
265#define pipe_debug_message(cb, type, fmt, ...) do { \
266   static unsigned id = 0; \
267   if ((cb) && (cb)->debug_message) { \
268      _pipe_debug_message(cb, &id, \
269                          PIPE_DEBUG_TYPE_ ## type, \
270                          fmt, ##__VA_ARGS__); \
271   } \
272} while (0)
273
274struct pipe_debug_callback;
275
276void
277_pipe_debug_message(
278   struct pipe_debug_callback *cb,
279   unsigned *id,
280   enum pipe_debug_type type,
281   const char *fmt, ...) _util_printf_format(4, 5);
282
283
284/**
285 * Used by debug_dump_enum and debug_dump_flags to describe symbols.
286 */
287struct debug_named_value
288{
289   const char *name;
290   uint64_t value;
291   const char *desc;
292};
293
294
295/**
296 * Some C pre-processor magic to simplify creating named values.
297 *
298 * Example:
299 * @code
300 * static const debug_named_value my_names[] = {
301 *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
302 *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
303 *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
304 *    DEBUG_NAMED_VALUE_END
305 * };
306 *
307 *    ...
308 *    debug_printf("%s = %s\n",
309 *                 name,
310 *                 debug_dump_enum(my_names, my_value));
311 *    ...
312 * @endcode
313 */
314#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol, NULL}
315#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc}
316#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL}
317
318
319/**
320 * Convert a enum value to a string.
321 */
322const char *
323debug_dump_enum(const struct debug_named_value *names,
324                unsigned long value);
325
326const char *
327debug_dump_enum_noprefix(const struct debug_named_value *names,
328                         const char *prefix,
329                         unsigned long value);
330
331
332/**
333 * Convert binary flags value to a string.
334 */
335const char *
336debug_dump_flags(const struct debug_named_value *names,
337                 unsigned long value);
338
339
340/**
341 * Function enter exit loggers
342 */
343#ifdef DEBUG
344int debug_funclog_enter(const char* f, const int line, const char* file);
345void debug_funclog_exit(const char* f, const int line, const char* file);
346void debug_funclog_enter_exit(const char* f, const int line, const char* file);
347
348#define DEBUG_FUNCLOG_ENTER() \
349   int __debug_decleration_work_around = \
350      debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__)
351#define DEBUG_FUNCLOG_EXIT() \
352   do { \
353      (void)__debug_decleration_work_around; \
354      debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
355      return; \
356   } while(0)
357#define DEBUG_FUNCLOG_EXIT_RET(ret) \
358   do { \
359      (void)__debug_decleration_work_around; \
360      debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
361      return ret; \
362   } while(0)
363#define DEBUG_FUNCLOG_ENTER_EXIT() \
364   debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__)
365
366#else
367#define DEBUG_FUNCLOG_ENTER() \
368   int __debug_decleration_work_around
369#define DEBUG_FUNCLOG_EXIT() \
370   do { (void)__debug_decleration_work_around; return; } while(0)
371#define DEBUG_FUNCLOG_EXIT_RET(ret) \
372   do { (void)__debug_decleration_work_around; return ret; } while(0)
373#define DEBUG_FUNCLOG_ENTER_EXIT()
374#endif
375
376
377/**
378 * Get option.
379 *
380 * It is an alias for getenv on Linux.
381 *
382 * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
383 * endings with one option per line as
384 *
385 *   NAME=value
386 *
387 * This file must be terminated with an extra empty line.
388 */
389const char *
390debug_get_option(const char *name, const char *dfault);
391
392boolean
393debug_get_bool_option(const char *name, boolean dfault);
394
395long
396debug_get_num_option(const char *name, long dfault);
397
398uint64_t
399debug_get_flags_option(const char *name,
400                       const struct debug_named_value *flags,
401                       uint64_t dfault);
402
403#define DEBUG_GET_ONCE_OPTION(suffix, name, dfault) \
404static const char * \
405debug_get_option_ ## suffix (void) \
406{ \
407   static boolean first = TRUE; \
408   static const char * value; \
409   if (first) { \
410      first = FALSE; \
411      value = debug_get_option(name, dfault); \
412   } \
413   return value; \
414}
415
416#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \
417static boolean \
418debug_get_option_ ## sufix (void) \
419{ \
420   static boolean first = TRUE; \
421   static boolean value; \
422   if (first) { \
423      first = FALSE; \
424      value = debug_get_bool_option(name, dfault); \
425   } \
426   return value; \
427}
428
429#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \
430static long \
431debug_get_option_ ## sufix (void) \
432{ \
433   static boolean first = TRUE; \
434   static long value; \
435   if (first) { \
436      first = FALSE; \
437      value = debug_get_num_option(name, dfault); \
438   } \
439   return value; \
440}
441
442#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \
443static unsigned long \
444debug_get_option_ ## sufix (void) \
445{ \
446   static boolean first = TRUE; \
447   static unsigned long value; \
448   if (first) { \
449      first = FALSE; \
450      value = debug_get_flags_option(name, flags, dfault); \
451   } \
452   return value; \
453}
454
455
456#ifdef	__cplusplus
457}
458#endif
459
460#endif /* U_DEBUG_H_ */
461