More documentation fixes, formatting, cosmetic, wording
[nobug.git] / src / nobug.h
blob80d6e2dea064aeb9581a15b4aca0d1e299bc9972
1 /*
2 This file is part of the NoBug debugging library.
4 Copyright (C)
5 2006, 2007, 2008, 2009, Christian Thaeter <ct@pipapo.org>
6 2010, Christian Thaeter <ct@pipapo.org>
7 2009, Francois Kubler <ih8tehuman@free.fr>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program 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
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
22 #ifndef NOBUG_H
23 #define NOBUG_H
25 #ifndef NOBUG_LIBNOBUG_C /* not when building libnobug */
26 #ifdef NDEBUG
27 #ifdef EBUG_ALPHA
28 #error NDEBUG incompatible with -DEBUG_ALPHA
29 #endif
30 #ifdef EBUG_BETA
31 #error NDEBUG incompatible with -DEBUG_BETA
32 #endif
33 #endif
35 #if defined(EBUG_ALPHA)
36 # define NOBUG_MODE_ALPHA 1
37 # define NOBUG_MODE_BETA 0
38 # define NOBUG_MODE_RELEASE 0
39 #elif defined(EBUG_BETA)
40 # define NOBUG_MODE_ALPHA 0
41 # define NOBUG_MODE_BETA 1
42 # define NOBUG_MODE_RELEASE 0
43 #elif defined(NDEBUG)
44 # define NOBUG_MODE_ALPHA 0
45 # define NOBUG_MODE_BETA 0
46 # define NOBUG_MODE_RELEASE 1
47 #else
48 #error no debug level and no NDEBUG defined
49 #endif
50 #endif /* NOBUG_LIBNOBUG_C */
53 HEADERS
56 #include <syslog.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <stdio.h>
60 #include <stdarg.h>
61 #include <inttypes.h>
63 #ifdef HAVE_EXECINFO_H
64 # ifndef NOBUG_USE_EXECINFO
65 # define NOBUG_USE_EXECINFO 1
66 # endif
67 #else
68 # undef NOBUG_USE_EXECINFO
69 # define NOBUG_USE_EXECINFO 0
70 #endif
72 #if NOBUG_USE_EXECINFO
73 #include <execinfo.h>
74 #endif
76 #if defined(HAVE_VALGRIND) && !defined(NVALGRIND)
77 # ifndef NOBUG_USE_VALGRIND
78 # define NOBUG_USE_VALGRIND 1
79 # endif
80 #else
81 # undef NOBUG_USE_VALGRIND
82 # define NOBUG_USE_VALGRIND 0
83 #endif
85 #if NOBUG_USE_VALGRIND
86 #include <valgrind.h>
87 #endif
89 #ifdef HAVE_PTHREAD
90 # ifndef NOBUG_USE_PTHREAD
91 # define NOBUG_USE_PTHREAD 1
92 # endif
93 #else
94 # ifdef NOBUG_USE_PTHREAD
95 # undef NOBUG_USE_PTHREAD
96 # endif
97 # define NOBUG_USE_PTHREAD 0
98 #endif
100 #if NOBUG_USE_PTHREAD
101 #include <pthread.h>
102 #endif
106 figure out how to find out the current function name, this is compiler and language dependent
108 #if !defined(NOBUG_FUNC) && defined(__STDC_VERSION__)
109 /* C99 defines __func__ */
110 # if __STDC_VERSION__ >= 199901L
111 # define NOBUG_FUNC __func__
112 # endif
113 #endif
115 #if !defined(NOBUG_FUNC) && defined(__GNUC__)
116 /* the gnu compiler (since 2.x) defines __FUNCTION__ */
117 # if __GNUC__ >= 2
118 # define NOBUG_FUNC __FUNCTION__
119 # endif
120 #endif
122 #if !defined(NOBUG_FUNC) && defined(__SUNPRO_C)
123 /* the sun C compiler defines __FUNCTION__, the version is determined by a sochastic test, please report! */
124 # if __SUNPRO_C >= 0x5100
125 # define NOBUG_FUNC __FUNCTION__
126 # endif
127 #endif
129 /* add more heuristics here... */
132 /* generic fallback, check for some common definitions (its not guranteed that this symbols are preprocessor defines), just some guesswork */
133 #ifndef NOBUG_FUNC
134 # ifdef __func__
135 # define NOBUG_FUNC __func__
136 # elif defined(__FUNCTION__)
137 # define NOBUG_FUNC __FUNCTION__
138 # else
139 /* finally a fallback when nothing found */
140 # define NOBUG_FUNC "-"
141 # endif
142 #endif
146 //assertions HEAD- Assertions;;
147 //assertions
148 //assertions The assertion set of macros provide a convenient status check
149 //assertions on whether to continue running, or gracefully exit execution
150 //assertions as some condition was not fulfilled.
151 //assertions
152 //assertions PARA CHECK; CHECK; unnconditional assertion for test suites
153 //assertions
154 //assertions CHECK(expr, ...)
155 //assertions CHECK_IF(when, expr, ...)
156 //assertions
157 //assertions This assertion is never optimized out. Its main purpose is in implementing
158 //assertions test suites where one would like to assert tests independent of the build level.
159 //assertions
161 #define NOBUG_CHECK(expr, ...) \
162 NOBUG_ASSERT_(expr, "CHECK", NOBUG_CONTEXT, ""__VA_ARGS__)
164 #define NOBUG_CHECK_IF(when, expr, ...) \
165 NOBUG_WHEN(when, NOBUG_CHECK(expr, ""__VA_ARGS__))
169 //assertions PARA REQUIRE; REQUIRE; preconditions (input parameters)
170 //assertions
171 //assertions REQUIRE(expr, ...)
172 //assertions REQUIRE_IF(when, expr, ...)
173 //assertions NOBUG_REQUIRE_CTX(expr, context,...)
174 //assertions NOBUG_REQUIRE_IF_CTX(when, expr, context, ...)
175 //assertions
176 //assertions Precondition (input) check. Use these macros to validate the input a
177 //assertions function receives. The checks are enabled in *ALPHA* and *BETA* builds,
178 //assertions but have not effect in *RELEASE* builds.
179 //assertions
181 #define NOBUG_REQUIRE(expr, ...) \
182 NOBUG_REQUIRE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
184 #define NOBUG_REQUIRE_CTX(expr, context, ...) \
185 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", context, ""__VA_ARGS__))
188 #define NOBUG_REQUIRE_IF(when, expr, context,...) \
189 NOBUG_REQUIRE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
191 #define NOBUG_REQUIRE_IF_CTX(when, expr, context,...) \
192 NOBUG_IF_NOT_RELEASE ( \
193 NOBUG_WHEN(when, NOBUG_REQUIRE_CTX(expr, context, ""__VA_ARGS__)) \
198 //assertions PARA ENSURE; ENSURE; postconditions (computation outcomes)
199 //assertions
200 //assertions ENSURE(expr, ...)
201 //assertions ENSURE_IF(when, expr, ...)
202 //assertions NOBUG_ENSURE_CTX(expr, context, ...)
203 //assertions NOBUG_ENSURE_IF_CTX(when, expr, context, ...)
204 //assertions
205 //assertions Postcondition (progress/output) check. Use these macros to validate the
206 //assertions data a function produces (example: return value). `ENSURE` is enabled
207 //assertions unconditionally in *ALPHA* builds and have no effect in *BETA* builds for
208 //assertions scopes which are tagged as `CHECKED`.
209 //assertions
210 //assertions The `ENSURE_IF` variants are enabled in *ALPHA* and *BETA* builds.
211 //assertions
212 //assertions In *RELEASE* builds these checks are optimized out.
213 //assertions
215 #define NOBUG_ENSURE(expr, ...) \
216 NOBUG_ENSURE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
218 #define NOBUG_ENSURE_CTX(expr, context, ...) \
219 NOBUG_IF_ALPHA (NOBUG_ASSERT_(expr, "POSTCONDITION", \
220 context, ""__VA_ARGS__)) \
221 NOBUG_IF_BETA ( \
222 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
223 NOBUG_ASSERT_(expr, "POSTCONDITION", \
224 context, ""__VA_ARGS__) \
229 #define NOBUG_ENSURE_IF(when, expr, ...) \
230 NOBUG_ENSURE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
232 #define NOBUG_ENSURE_IF_CTX(when, expr, context, ...) \
233 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE_CTX(expr, context, ""__VA_ARGS__)))
237 //assertions PARA ASSERT; ASSERT; generic assertion
238 //assertions
239 //assertions ASSERT(expr, ...)
240 //assertions ASSERT_IF(when, expr, ...)
241 //assertions NOBUG_ASSERT_CTX(expr, context, ...)
242 //assertions NOBUG_ASSERT_IF_CTX(when, expr, context, ...)
243 //assertions
244 //assertions Generic check. Use these macros when you want to validate something
245 //assertions which doesn't fall into one of the above categories. Generally to be
246 //assertions avoided! The checks are enabled in *ALPHA* and *BETA* builds and
247 //assertions have no effect in *RELEASE* builds.
248 //assertions
250 #define NOBUG_ASSERT(expr, ...) \
251 NOBUG_ASSERT_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
253 #define NOBUG_ASSERT_CTX(expr, context, ...) \
254 NOBUG_IF_NOT_RELEASE( \
255 NOBUG_ASSERT_(expr, "ASSERTION", \
256 context, ""__VA_ARGS__) \
260 #define NOBUG_ASSERT_IF(when, expr, ...) \
261 NOBUG_ASSERT_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
263 #define NOBUG_ASSERT_IF_CTX(when, expr, context, ...) \
264 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT_CTX(expr, context, ""__VA_ARGS__)))
268 //assertions PARA assert; assert; C standard assertion
269 //assertions
270 //assertions assert(expr)
271 //assertions
272 //assertions NoBug overrides the standard `assert` macro, using `NOBUG_ASSERT`.
273 //assertions This is just a compatibility feature, its use is not suggested.
274 //assertions
276 #undef assert
277 #define assert(expr) NOBUG_ASSERT(expr)
281 low level assert
283 #ifdef __GNUC__
284 #define NOBUG_ASSERT_(expr, what, context, fmt, ...) \
285 NOBUG_WHEN (!(expr), \
286 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
287 what, context, "(%s) " fmt, \
288 #expr, ## __VA_ARGS__); \
289 NOBUG_BACKTRACE_CTX(context); \
290 NOBUG_ABORT \
292 #else /* , ## __VA_ARGS__ eating the comma when the arglist is empty is a gcc extension, fallback for other compilers */
293 #define NOBUG_ASSERT_(expr, what, context, ...) \
294 NOBUG_WHEN (!(expr), \
295 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
296 what, context, \
297 ""__VA_ARGS__); \
298 NOBUG_BACKTRACE_CTX(context); \
299 NOBUG_ABORT \
301 #endif
304 //assertions PARA INVARIANT; INVARIANT; validate invariant state
305 //assertions
306 //assertions INVARIANT(type, pointer, depth)
307 //assertions INVARIANT_IF(when,type, pointer, depth)
308 //assertions INVARIANT_ASSERT(expr, ...)
309 //assertions
310 //assertions Checking invariants. You can provide more complex checking functions
311 //assertions which test the validity of datastructures. Invariants are only enabled
312 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
313 //assertions otherwise optimized out.
314 //assertions
315 //assertions TODO: describe how to create invariant checks
316 //assertions
317 // 'invariant_context' must be passed in
319 #define NOBUG_INVARIANT(type, pointer, depth, extra) \
320 NOBUG_IF_ALPHA( \
321 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
322 NOBUG_CAT3(nobug_, type,_invariant)(pointer, depth, \
323 NOBUG_CONTEXT, extra) \
328 #define NOBUG_INVARIANT_IF(when, type, pointer, depth, extra) \
329 NOBUG_IF_ALPHA( \
330 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
331 NOBUG_WHEN (when, \
332 NOBUG_CAT3(nobug_, type,_invariant)(pointer, depth, \
333 NOBUG_CONTEXT, \
334 extra) \
338 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
339 NOBUG_ASSERT_(expr, "INVARIANT", invariant_context, ""__VA_ARGS__)
341 #define NOBUG_INVARIANT_ASSERT_IF(when, expr, ...) \
342 NOBUG_WHEN (when, \
343 NOBUG_ASSERT_(expr, "INVARIANT", invariant_context, ""__VA_ARGS__) \
347 checked/unchecked tagged scopes
349 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
351 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
353 #define NOBUG_UNCHECKED \
354 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
355 NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
359 /*TODO dump-level for flags instead limits[0]*/
361 //dumpmacros PARA DUMP; DUMP; dumping datastructures
362 //dumpmacros
363 //dumpmacros DUMP(flag, type, pointer, depth, extra)
364 //dumpmacros DUMP_IF(when, flag, type, pointer, depth, extra)
365 //dumpmacros
366 //dumpmacros These macros call a data structure dump of the object (`pointer`) in question.
367 //dumpmacros `DUMP` has only effect in *ALPHA* and *BETA* builds, `DUMP_IF` is also
368 //dumpmacros enabled for RELEASE builds.
369 //dumpmacros
370 //dumpmacros `extra` is a void* which is transparently passed around and can be used to
371 //dumpmacros pass a particular state around. NoBug does not alter this.
372 //dumpmacros
374 #define NOBUG_DUMP(flag, type, pointer, depth, extra) \
375 NOBUG_IF_NOT_RELEASE( \
376 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
377 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT, extra) \
381 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth, extra) \
382 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET] && when, \
383 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT, extra) \
388 //dumpmacros PARA DUMP_LOG; DUMP_LOG; logging helper for dumping
389 //dumpmacros
390 //dumpmacros DUMP_LOG(...)
391 //dumpmacros DUMP_LOG_IF(when, ...)
392 //dumpmacros
393 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
394 //dumpmacros
396 #define NOBUG_DUMP_LOG(...) \
397 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
398 "DUMP", dump_context, \
399 ""__VA_ARGS__)
401 #define NOBUG_DUMP_LOG_IF(expr, ...) \
402 NOBUG_WHEN (expr, \
403 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
404 "DUMP", dump_context, \
405 ""__VA_ARGS__) \
410 //dumpmacros PARA DUMP_LEVEL; DUMP_LEVEL; logging level at which DUMPs are done
411 //dumpmacros
412 //dumpmacros #define NOBUG_DUMP_LEVEL ...
413 //dumpmacros
414 //dumpmacros Dumping is by default done at `LOG_DEBUG` level, this can be overridden by
415 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other logging level.
416 //dumpmacros
418 #ifndef NOBUG_DUMP_LEVEL
419 #define NOBUG_DUMP_LEVEL LOG_DEBUG
420 #endif
424 //logmacros HEAD- Macros That Log Information ;;
425 //logmacros
426 //logmacros Logging targets a flag (except for `ECHO`) and is done at a log-level related to syslog levels.
427 //logmacros
428 //logmacros PARA ECHO; ECHO; unconditional logging for tests
429 //logmacros
430 //logmacros ECHO(...)
431 //logmacros
432 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
433 //logmacros testsuites where one would like to print and log messages independent of the build level
434 //logmacros
436 #define NOBUG_ECHO(...) \
437 NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_NOTICE, "ECHO", NOBUG_CONTEXT, ""__VA_ARGS__)
441 //logmacros PARA ALERT; ALERT; about to die
442 //logmacros
443 //logmacros ALERT(flag, ...)
444 //logmacros ALERT_IF(when, flag, ...)
445 //logmacros NOBUG_ALERT_CTX(flag, context, ...)
446 //logmacros NOBUG_ALERT_IF_CTX(when, flag, context, ...)
447 //logmacros
448 //logmacros This is the most critical condition that might be registered by
449 //logmacros an application. Situations might arise when the application
450 //logmacros encounters such a serious error that can only be adequately treated
451 //logmacros by, for example, safely shutting down the application.
452 //logmacros
454 #define NOBUG_ALERT(flag, ...) \
455 NOBUG_ALERT_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
457 #define NOBUG_ALERT_IF(expr, flag, ...) \
458 NOBUG_ALERT_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
461 #define NOBUG_ALERT_CTX(flag, context, ...) \
462 NOBUG_LOG_CTX(flag, LOG_ALERT, context, ""__VA_ARGS__)
464 #define NOBUG_ALERT_IF_CTX(expr, flag, context, ...) \
465 NOBUG_LOG_IF(expr, flag, LOG_ALERT, context, ""__VA_ARGS__)
470 //logmacros PARA CRITICAL; CRITICAL; can not continue
471 //logmacros
472 //logmacros CRITICAL(flag, ...)
473 //logmacros CRITICAL_IF(when, flag, ...)
474 //logmacros NOBUG_CRITICAL_CTX(flag, context, ...)
475 //logmacros NOBUG_CRITICAL_IF_CTX(when, flag, context, ...)
476 //logmacros
477 //logmacros An error which can not be handled occured but the application does not need to be
478 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
479 //logmacros
481 #define NOBUG_CRITICAL(flag, ...) \
482 NOBUG_CRITICAL_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
484 #define NOBUG_CRITICAL_CTX(flag, context, ...) \
485 NOBUG_LOG_CTX(flag, LOG_CRIT, context, ""__VA_ARGS__)
488 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
489 NOBUG_CRITICAL_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
491 #define NOBUG_CRITICAL_IF_CTX(expr, flag, context, ...) \
492 NOBUG_LOG_IF_CTX(expr, flag, LOG_CRIT, context, ""__VA_ARGS__)
496 //logmacros PARA ERROR; ERROR; something gone wrong
497 //logmacros
498 //logmacros ERROR(flag, ...)
499 //logmacros ERROR_IF(when, flag, ...)
500 //logmacros NOBUG_ERROR_CTX(flag, context, ...)
501 //logmacros NOBUG_ERROR_IF_CTX(when, flag, context, ...)
502 //logmacros
503 //logmacros This is used when an application registers an error
504 //logmacros and appropriate action will have to be taken.
505 //logmacros
507 #define NOBUG_ERROR(flag, ...) \
508 NOBUG_ERROR_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
510 #define NOBUG_ERROR_CTX(flag, context, ...) \
511 NOBUG_LOG_CTX(flag, LOG_ERR, context, ""__VA_ARGS__)
514 #define NOBUG_ERROR_IF(expr, flag, ...) \
515 NOBUG_ERROR_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
517 #define NOBUG_ERROR_IF_CTX(expr, flag, context, ...) \
518 NOBUG_LOG_IF_CTX(expr, flag, LOG_ERR, context, ""__VA_ARGS__)
522 //logmacros PARA WARN; WARN; unexpected fixable error
523 //logmacros
524 //logmacros WARN(flag, ...)
525 //logmacros WARN_IF(when, flag, ...)
526 //logmacros NOBUG_WARN_CTX(flag, context, ...)
527 //logmacros NOBUG_WARN_IF_CTX(when, flag, context, ...)
528 //logmacros
529 //logmacros When an application encounters a rare and unexpected
530 //logmacros situation, these macros can be used.
531 //logmacros
533 #define NOBUG_WARN(flag, ...) \
534 NOBUG_WARN_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
536 #define NOBUG_WARN_CTX(flag, context, ...) \
537 NOBUG_LOG_CTX(flag, LOG_WARNING, context, ""__VA_ARGS__)
540 #define NOBUG_WARN_IF(expr, flag, ...) \
541 NOBUG_WARN_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
543 #define NOBUG_WARN_IF_CTX(expr, flag, context, ...) \
544 NOBUG_LOG_IF_CTX(expr, flag, LOG_WARNING, context, ""__VA_ARGS__)
548 //logmacros PARA INFO; INFO; progress message
549 //logmacros
550 //logmacros INFO(flag, ...)
551 //logmacros INFO_IF(when, flag, ...)
552 //logmacros NOBUG_INFO_CTX(flag, context, ...)
553 //logmacros NOBUG_INFO_IF_CTX(when, flag, context, ...)
554 //logmacros
555 //logmacros It may be benificial to output information at various
556 //logmacros locations throughout the code, e.g., messages on programme
557 //logmacros progress.
558 //logmacros
560 #define NOBUG_INFO(flag, ...) \
561 NOBUG_INFO_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
563 #define NOBUG_INFO_CTX(flag, context, ...) \
564 NOBUG_LOG_CTX(flag, LOG_INFO, context, ""__VA_ARGS__)
567 #define NOBUG_INFO_IF(expr, flag, ...) \
568 NOBUG_INFO_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
570 #define NOBUG_INFO_IF_CTX(expr, flag, context, ...) \
571 NOBUG_LOG_IF_CTX(expr, flag, LOG_INFO, context, ""__VA_ARGS__)
575 //logmacros PARA NOTICE; NOTICE; detailed progress message
576 //logmacros
577 //logmacros NOTICE(flag, ...)
578 //logmacros NOTICE_IF(when, flag, ...)
579 //logmacros NOBUG_NOTICE_CTX(flag, context, ...)
580 //logmacros NOBUG_NOTICE_IF_CTX(when, flag, context, ...)
581 //logmacros
582 //logmacros Same as the INFO() macros, except more verbose.
583 //logmacros
585 #define NOBUG_NOTICE(flag, ...) \
586 NOBUG_NOTICE_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
588 #define NOBUG_NOTICE_CTX(flag, context, ...) \
589 NOBUG_LOG_CTX(flag, LOG_NOTICE, context, ""__VA_ARGS__)
592 #define NOBUG_NOTICE_IF(expr, flag, ...) \
593 NOBUG_NOTICE_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
595 #define NOBUG_NOTICE_IF_CTX(expr, flag, context, ...) \
596 NOBUG_LOG_IF_CTX(expr, flag, LOG_NOTICE, context, ""__VA_ARGS__)
599 //logmacros PARA TRACE; TRACE; debugging level message
600 //logmacros
601 //logmacros TRACE(flag, ...)
602 //logmacros TRACE_IF(when, flag, ...)
603 //logmacros NOBUG_TRACE_CTX(flag, context, ...)
604 //logmacros NOBUG_TRACE_IF_CTX(when, flag, context, ...)
605 //logmacros
606 //logmacros The same as the NOTICE() macros, except very fine-grained information.
607 //logmacros a common use case is to put just `TRACE(debugflag)` just at the begin of every
608 //logmacros non-trivial function. This allows to see fine grained application progress in the log.
609 //logmacros
610 //logmacros NOTE: `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
611 //logmacros
613 #define NOBUG_TRACE(flag, ...) \
614 NOBUG_TRACE_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
616 #define NOBUG_TRACE_CTX(flag, context, ...) \
617 NOBUG_LOG_CTX(flag, LOG_DEBUG, context, ""__VA_ARGS__)
620 #define NOBUG_TRACE_IF(expr, flag, ...) \
621 NOBUG_TRACE_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
623 #define NOBUG_TRACE_IF_CTX(expr, flag, context, ...) \
624 NOBUG_LOG_IF_CTX(expr, flag, LOG_DEBUG, context, ""__VA_ARGS__)
628 //logmacros PARA LOG; LOG; generic logging
629 //logmacros
630 //logmacros NOBUG_LOG_CTX(flag, lvl, context, ...)
631 //logmacros NOBUG_LOG_IF_CTX(when, flag, lvl, context, ...)
632 //logmacros
633 //logmacros Generic logging macro which takes the level explicitly.
634 //logmacros Avoid this, unless you implement your own logging facilities.
635 //logmacros
637 #define NOBUG_LOG_CTX(flag, lvl, context, ...) \
638 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LVL(lvl), context, ""__VA_ARGS__)
641 #define NOBUG_LOG_IF_CTX(expr, flag, lvl, context, ...) \
642 NOBUG_WHEN (expr, \
643 NOBUG_LOG_CTX(flag, lvl, context, ""__VA_ARGS__) \
647 //logmacros INDEX LOG_EMERG; LOG_EMERG; no logging macro for emergency logging
648 //logmacros
649 //logmacros NOTE: there is no logging macro for `LOG_EMERG`, this is only used by the assertions as a fatal message
650 //logmacros
654 low level logging handler
656 Note: all fmt concatenations use an empty string ""__VA_ARG__
657 except this one which must use a single space " " before __VA_ARGS__ for formatting the log message correctly (and silence a gcc warning)
659 #define NOBUG_LOG_(flag, lvl, what, context, ...) \
660 NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER], \
661 nobug_log (flag, lvl, what, context, " "__VA_ARGS__) \
665 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
666 #define NOBUG_LVL_0 "EMERG"
667 #define NOBUG_LVL_1 "ALERT"
668 #define NOBUG_LVL_2 "CRIT"
669 #define NOBUG_LVL_3 "ERR"
670 #define NOBUG_LVL_4 "WARNING"
671 #define NOBUG_LVL_5 "NOTICE"
672 #define NOBUG_LVL_6 "INFO"
673 #define NOBUG_LVL_7 "TRACE"
676 //logmacros PARA LOG_BASELIMIT; LOG_BASELIMIT; minimum compliled-in logging limit
677 //logmacros
678 //logmacros NOBUG_LOG_BASELIMIT_ALPHA
679 //logmacros NOBUG_LOG_BASELIMIT_BETA
680 //logmacros NOBUG_LOG_BASELIMIT_RELEASE
681 //logmacros NOBUG_LOG_BASELIMIT
682 //logmacros
683 //logmacros Anything more detailed than this base limits will be optimized out.
684 //logmacros This is used to reduce the logging overhead for *RELEASE* builds.
685 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
686 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
687 //logmacros builds to log the application progress only coarsely.
688 //logmacros
689 //logmacros These macros can be defined before including 'nobug.h' to some other
690 //logmacros log level (as defined in 'syslog.h').
691 //logmacros
693 #ifndef NOBUG_LOG_BASELIMIT_ALPHA
694 #define NOBUG_LOG_BASELIMIT_ALPHA LOG_DEBUG
695 #endif
697 #ifndef NOBUG_LOG_BASELIMIT_BETA
698 #define NOBUG_LOG_BASELIMIT_BETA LOG_DEBUG
699 #endif
701 #ifndef NOBUG_LOG_BASELIMIT_RELEASE
702 #define NOBUG_LOG_BASELIMIT_RELEASE LOG_NOTICE
703 #endif
705 #ifndef NOBUG_LOG_BASELIMIT
706 #define NOBUG_LOG_BASELIMIT \
707 NOBUG_IF_ALPHA(NOBUG_LOG_BASELIMIT_ALPHA) \
708 NOBUG_IF_BETA(NOBUG_LOG_BASELIMIT_BETA) \
709 NOBUG_IF_RELEASE(NOBUG_LOG_BASELIMIT_RELEASE)
710 #endif
714 //srccontext HEAD~ Source Contexts; NOBUG_CONTEXT; pass information about the source location
715 //srccontext
716 //srccontext NOBUG_CONTEXT
717 //srccontext NOBUG_CONTEXT_NOFUNC
718 //srccontext
719 //srccontext NoBug passes information about the source location of a given statement in
720 //srccontext `const struct nobug_context` structures. These can be generated with
721 //srccontext `NOBUG_CONTEXT` or `NOBUG_CONTEXT_NOFUNC`. The later one doesn't define a
722 //srccontext function name and must be used when the function context is not available
723 //srccontext like in static initialization etc..
724 //srccontext
727 #ifndef __cplusplus
728 #define NOBUG_CONTEXT ((const struct nobug_context){__FILE__, __LINE__, NOBUG_FUNC})
730 #define NOBUG_CONTEXT_NOFUNC ((const struct nobug_context){__FILE__, __LINE__, "-"})
732 #define NOBUG_CONTEXT_NIL ((const struct nobug_context){"-", 0, "-"})
733 #else
735 #define NOBUG_CONTEXT (nobug_context(__FILE__, __LINE__, NOBUG_FUNC))
737 #define NOBUG_CONTEXT_NOFUNC (nobug_context(__FILE__, __LINE__, "-"))
739 #define NOBUG_CONTEXT_NIL (nobug_context("-", 0, "-"))
740 #endif
743 //annotations HEAD- Source Code Annotations;;
744 //annotations
745 //annotations Obsolete, buggy or precarious code can be marked in the code itself in
746 //annotations comments at the location where the code occurs. However these code
747 //annotations locations can be easily overlooked, especially in large projects. The
748 //annotations advantage of this tagging scheme is that it provides an additional
749 //annotations instrument to alert or remind the programmer that there is still dubious
750 //annotations code embedded in the application. This tagging scheme not only informs
751 //annotations the programmer at compile time that there is code in the application
752 //annotations that needs attending to, but long after compilitation a test team
753 //annotations might become aware of dubious code due to runtime messages.
754 //annotations
758 alpha beta release
759 DEPRECATED log nothing wont compile
761 //annotations
762 //annotations PARA DEPRECATED; DEPRECATED; to be discarded in future
763 //annotations
764 //annotations DEPRECATED(...)
765 //annotations
766 //annotations Use this macro to identify code that is depreciated
767 //annotations and should not be used in future or productive code.
768 //annotations
770 #define NOBUG_DEPRECATED(...) \
771 NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN, \
772 "DEPRECATED", NOBUG_CONTEXT, ""__VA_ARGS__) \
774 NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
778 alpha beta release
779 UNIMPLEMENTED abort abort wont compile
781 //annotations PARA UNIMPLEMENTED; UNIMPLEMENTED; not yet implemented
782 //annotations
783 //annotations UNIMPLEMENTED(...)
784 //annotations
785 //annotations Use this macro to identify code that is functionally
786 //annotations not yet complete and should not be used. This is convenient
787 //annotations for code under development or being reviewed.
788 //annotations
790 #define NOBUG_UNIMPLEMENTED(...) \
791 NOBUG_IF_NOT_RELEASE ( do { \
792 NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG, \
793 "UNIMPLEMENTED", NOBUG_CONTEXT, ""__VA_ARGS__); \
794 NOBUG_ABORT; \
795 } while (0)) \
796 NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
800 alpha beta release
801 FIXME log wont compile wont compile
803 //annotations PARA FIXME; FIXME; known bug
804 //annotations
805 //annotations FIXME(...)
806 //annotations
807 //annotations Use this macro to mark a known and unfixed bug.
808 //annotations
810 #define NOBUG_FIXME(...) \
811 NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT, \
812 "FIXME", NOBUG_CONTEXT, ""__VA_ARGS__))) \
813 NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(__VA_ARGS__)) \
814 NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
818 alpha beta release
819 TODO log log wont compile
821 //annotations PARA TODO; TODO; things to be done
822 //annotations
823 //annotations TODO(...)
824 //annotations
825 //annotations Enhancement or non-critical bug to be done soon.
826 //annotations
828 #define NOBUG_TODO(...) \
829 NOBUG_IF_NOT_RELEASE ( \
830 NOBUG_ONCE ( \
831 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE, \
832 "TODO", NOBUG_CONTEXT, ""__VA_ARGS__); \
833 )) \
834 NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
838 alpha beta release
839 PLANNED log nothing nothing
841 //annotations PARA PLANNED; PLANNED; ideas for future
842 //annotations
843 //annotations PLANNED(...)
844 //annotations
845 //annotations Future enhancement, optimization to similar which has no side effect on the current program.
846 //annotations
848 #define NOBUG_PLANNED(...) \
849 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO, \
850 "PLANNED", NOBUG_CONTEXT, ""__VA_ARGS__)))
854 alpha beta release
855 NOTREACHED abort abort nothing
857 //annotations PARA NOTREACHED; NOTREACHED; code path never taken
858 //annotations
859 //annotations NOTREACHED(...)
860 //annotations
861 //annotations Code which must never be reached.
862 //annotations
864 #define NOBUG_NOTREACHED(...) \
865 NOBUG_IF_NOT_RELEASE( do { \
866 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
867 "NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__); \
868 NOBUG_ABORT; \
869 } while (0))
873 //annotations PARA ELSE_NOTREACHED; ELSE_NOTREACHED; alternative never taken
874 //annotations
875 //annotations ELSE_NOTREACHED(...)
876 //annotations
877 //annotations This macro is the same as `else NOTREACHED()`, but completely
878 //annotations optimized out in release builds.
879 //annotations
881 #define NOBUG_ELSE_NOTREACHED(...) \
882 NOBUG_IF_NOT_RELEASE( else do { \
883 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
884 "ELSE_NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__); \
885 NOBUG_ABORT; \
886 } while (0))
890 //faultinjection HEAD- Fault injection;;
891 //faultinjection
892 //faultinjection NoBug has some macros which can be used to simulate erroneous behaviour,
893 //faultinjection in other words, we can inject errors, or faults, into the code
894 //faultinjection using NoBug.
895 //faultinjection
896 //faultinjection PARA INJECT_GOODBAD; INJECT_GOODBAD; fault injection expression
897 //faultinjection
898 //faultinjection INJECT_GOODBAD(expr, good, bad)
899 //faultinjection
900 //faultinjection Substitutes to an expression and returns 'good' when expr is false and
901 //faultinjection 'bad' when expr is true. In BETA and RELEASE builds 'good' is always returned.
902 //faultinjection
904 #define NOBUG_INJECT_GOODBAD(expr, good, bad) \
905 NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);bad;}):good) \
906 NOBUG_IF_NOT_ALPHA(good)
910 //faultinjection PARA INJECT_FAULT; INJECT_FAULT; fault injection statement
911 //faultinjection
912 //faultinjection INJECT_FAULT(expr, bad)
913 //faultinjection
914 //faultinjection Substitutes to a statement which executes 'bad'
915 //faultinjection when expr is true. This is only available in ALPHA builds and
916 //faultinjection is optimitsed out in BETA and RELEASE builds.
917 //faultinjection
919 #define NOBUG_INJECT_FAULT(expr, bad) \
920 NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
924 //faultinjection PARA Setting the logging level for fault injections; INJECT_LEVEL; log level for fault injection
925 //faultinjection In both cases, when a fault is injected, it will be logged at
926 //faultinjection `NOBUG_INJECT_LEVEL` (default: `LOG_NOTICE`). This can be defined
927 //faultinjection before including 'nobug.h' to override it.
928 //faultinjection
930 #define NOBUG_INJECT_LOG(msg) \
931 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
932 "INJECT_FAULT", NOBUG_CONTEXT, \
933 msg)
936 #ifndef NOBUG_INJECT_LEVEL
937 #define NOBUG_INJECT_LEVEL LOG_NOTICE
938 #endif
942 //coverage HEAD- Coverage checking Macros;;
943 //coverage
944 //coverage PARA COVERAGE_FAULT; COVERAGE_FAULT; coverage fault injection, statement
945 //coverage
946 //coverage COVERAGE_FAULT(flag, ...)
947 //coverage
948 //coverage Injects the statement at `...` when simulating a failure. Only active in
949 //coverage ALPHA builds.
950 //coverage
952 #define NOBUG_COVERAGE_FAULT(flag, ...) \
953 NOBUG_IF_ALPHA(NOBUG_COVERAGE_FAULT_(flag, __VA_ARGS__)) \
954 NOBUG_IF_NOT_ALPHA(__VA_ARGS__)
957 #define NOBUG_COVERAGE_FAULT_(flag, ...) \
958 do { \
959 if (!nobug_thread_get ()->coverage_disable_cnt) \
961 struct nobug_coverage_record record = nobug_coverage_check (); \
962 if (record.state) \
964 NOBUG_COVERAGE_LOG(flag, record); \
965 if (record.state == 'F') \
967 __VA_ARGS__; \
971 } while (0)
976 //coverage PARA COVERAGE_GOODBAD; COVERAGE_GOODBAD; coverage fault injection, expression
977 //coverage
978 //coverage COVERAGE_GOODBAD(flag, good, bad)
979 //coverage
980 //coverage Substitutes to an expression and injects `bad` when simulating a failure and `good`
981 //coverage otherwise. Only active in ALPHA builds.
982 //coverage
984 #define NOBUG_COVERAGE_GOODBAD(flag, good, bad) \
985 NOBUG_IF_ALPHA(NOBUG_COVERAGE_GOODBAD_(flag, good, bad)) \
986 NOBUG_IF_NOT_ALPHA((good))
988 #define NOBUG_COVERAGE_GOODBAD_(flag, good, bad) \
989 ({ \
990 struct nobug_coverage_record record = {0,0}; \
991 if (!nobug_thread_get ()->coverage_disable_cnt) \
993 record = nobug_coverage_check (); \
994 if (record.state) \
995 NOBUG_COVERAGE_LOG(flag, record); \
997 record.state == 'F'?(bad):(good); \
1003 #define NOBUG_COVERAGE_LOG(flag, record) \
1004 NOBUG_LOG_( &NOBUG_FLAG(flag), NOBUG_COVERAGE_LEVEL, \
1005 "COVERAGE", NOBUG_CONTEXT, \
1006 "INJECT %"PRIx64": %s", \
1007 record.hash, \
1008 record.state == 'F'?"FAILURE":"PASS")
1012 //coverage PARA COVERAGE_LEVEL; COVERAGE_LEVEL; coverage fault injection log level
1013 //coverage
1014 //coverage #define NOBUG_COVERAGE_LEVEL ...
1015 //coverage
1016 //coverage Define the logging level in which fault-coverage logging is emitted.
1017 //coverage
1018 //coverage NOTE: Supressing log output with this level will not supress fault injection,
1019 //coverage actually the opposite is true since every newly seen failure path gets injected.
1020 //coverage This might be changed in future releases.
1021 //coverage
1022 // TODO see above, disable fault injection when not logged
1023 // if (NOBUG_EXPECT_FALSE(NOBUG_COVERAGE_LEVEL <= flag->limits[NOBUG_TARGET_???]))
1026 #ifndef NOBUG_COVERAGE_LEVEL
1027 #define NOBUG_COVERAGE_LEVEL LOG_NOTICE
1028 #endif
1033 //coverage PARA Disabling and enabling fault-coverage checks; COVERAGE_DISABLE; handle false positives
1034 //coverage
1035 //coverage NOBUG_COVERAGE_DISABLE
1036 //coverage NOBUG_COVERAGE_ENABLE
1037 //coverage
1038 //coverage Sometimes fault injection yields false positives, errors which may never happen in real life
1039 //coverage (and are possibly enforced with an ENSURE afterwards). For this cases coverage fault injection can be
1040 //coverage disabled temporarly and reenabled later. Disabling/enabling may nest and must properly match.
1041 //coverage
1044 #define NOBUG_COVERAGE_DISABLE \
1045 NOBUG_IF_ALPHA(unsigned nobug_coverage_disable_check = \
1046 nobug_thread_get ()->coverage_disable_cnt;) \
1047 NOBUG_IF_ALPHA(++ nobug_thread_get ()->coverage_disable_cnt)
1049 #define NOBUG_COVERAGE_ENABLE \
1050 NOBUG_IF_ALPHA(-- nobug_thread_get ()->coverage_disable_cnt); \
1051 ENSURE(nobug_coverage_disable_check == \
1052 nobug_thread_get ()->coverage_disable_cnt, \
1053 "COVERAGE ENABLE/DISABLE does not match")
1057 Flag handling
1059 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_, name)
1061 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
1064 #define NOBUG_DEFINE_FLAG(name) \
1065 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
1066 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
1067 struct nobug_flag NOBUG_FLAG(name) = \
1068 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
1069 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
1070 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
1071 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
1072 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
1073 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
1077 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
1078 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
1079 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
1080 NOBUG_DECLARE_FLAG(parent); \
1081 struct nobug_flag NOBUG_FLAG(name) = \
1082 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
1083 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
1084 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
1085 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
1086 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
1087 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
1091 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) \
1092 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
1093 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
1094 struct nobug_flag NOBUG_FLAG(name) = \
1095 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
1096 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
1097 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
1098 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
1099 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
1100 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
1104 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
1105 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
1106 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
1107 NOBUG_DECLARE_FLAG(parent); \
1108 struct nobug_flag NOBUG_FLAG(name) = \
1109 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
1110 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
1111 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
1112 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
1113 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
1114 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
1118 #define NOBUG_INIT_FLAG(name) \
1119 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT, NOBUG_CONTEXT_NOFUNC)
1122 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
1123 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default, NOBUG_CONTEXT_NOFUNC)
1126 #define NOBUG_CPP_DEFINE_FLAG(name) \
1127 NOBUG_FLAG_IF_DECLAREONLY( \
1128 NOBUG_DECLARE_FLAG(name); \
1129 extern int nobug_cppflag_##name \
1131 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
1132 NOBUG_DEFINE_FLAG(name); \
1133 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
1137 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
1138 NOBUG_FLAG_IF_DECLAREONLY( \
1139 NOBUG_DECLARE_FLAG(name); \
1140 extern int nobug_cppflag_##name \
1142 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
1143 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
1144 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
1148 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
1149 NOBUG_FLAG_IF_DECLAREONLY( \
1150 NOBUG_DECLARE_FLAG(name); \
1151 extern int nobug_cppflag_##name \
1153 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
1154 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
1155 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
1159 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
1160 NOBUG_FLAG_IF_DECLAREONLY( \
1161 NOBUG_DECLARE_FLAG(name); \
1162 extern int nobug_cppflag_##name \
1164 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
1165 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
1166 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
1170 #ifndef NOBUG_DECLARE_ONLY
1171 #define NOBUG_DECLARE_ONLY 0
1172 #endif
1174 #define NOBUG_FLAG_IF_DECLAREONLY(...) \
1175 NOBUG_IF(NOBUG_DECLARE_ONLY, __VA_ARGS__)
1177 #define NOBUG_FLAG_IF_NOT_DECLAREONLY(...) \
1178 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
1180 #ifdef __cplusplus
1181 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
1182 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
1183 #else
1184 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
1185 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, NOBUG_ERROR_CANT_DEFINE_AUTOINITIALIZED_CPP_FLAGS_IN_C)
1186 #endif
1188 #ifndef NOBUG_LOG_LIMIT_ALPHA
1189 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
1190 #endif
1191 #ifndef NOBUG_LOG_LIMIT_BETA
1192 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
1193 #endif
1194 #ifndef NOBUG_LOG_LIMIT_RELEASE
1195 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
1196 #endif
1198 #ifndef NOBUG_LOG_LIMIT
1199 # define NOBUG_LOG_LIMIT \
1200 NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA) \
1201 NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA) \
1202 NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
1203 #endif
1205 #ifndef NOBUG_LOG_TARGET_ALPHA
1206 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
1207 #endif
1208 #ifndef NOBUG_LOG_TARGET_BETA
1209 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
1210 #endif
1211 #ifndef NOBUG_LOG_TARGET_RELEASE
1212 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
1213 #endif
1215 #ifndef NOBUG_LOG_TARGET
1216 # define NOBUG_LOG_TARGET \
1217 NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA) \
1218 NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA) \
1219 NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
1220 #endif
1222 #define NOBUG_SET_LIMIT(flag, min) \
1223 NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
1227 //resourcemacros HEAD~ Resource tracking macros;;
1228 //resourcemacros INDEX RESOURCE_LOGGING; RESOURCE_LOGGING; switch resource logging on and off
1229 //resourcemacros INDEX RESOURCE_LOG_LEVEL; RESOURCE_LOG_LEVEL; select the log level for resource logging
1230 //resourcemacros
1231 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
1232 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
1233 //resourcemacros `LOG_DEBUG`.
1234 //resourcemacros
1236 #ifndef NOBUG_RESOURCE_LOGGING
1237 #define NOBUG_RESOURCE_LOGGING 1
1238 #endif
1240 #ifndef NOBUG_RESOURCE_LOG_LEVEL
1241 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
1242 #endif
1246 //resourcemacros PARA RESOURCE_HANDLE; RESOURCE_HANDLE; define resource handles
1247 //resourcemacros
1248 //resourcemacros RESOURCE_HANDLE(name)
1249 //resourcemacros RESOURCE_HANDLE_INIT(name)
1250 //resourcemacros RESOURCE_USER(name)
1251 //resourcemacros RESOURCE_USER_INIT(name)
1252 //resourcemacros
1253 //resourcemacros Define and initialize handles for to track resources.
1254 //resourcemacros
1255 //resourcemacros `name`::
1256 //resourcemacros identifer to be used for the handle
1257 //resourcemacros
1258 //resourcemacros There are two kinds of handles. Resource themself are abstracted with a
1259 //resourcemacros `RESOURCE_HANDLE` while uses of a resources are tracked by `RESOURCE_USER`
1260 //resourcemacros handle. These macros takes care that the declaration is optimized out
1261 //resourcemacros in the same manner as the rest of the resource tracker would be disabled.
1262 //resourcemacros You can still instantiate handles as `struct nobug_resource_record*` or
1263 //resourcemacros `struct nobug_resource_user*` in structures which must have a constant size
1264 //resourcemacros unconditional of the build level. The two `*_INIT` macros can be used to initialize
1265 //resourcemacros resource handles and are optimized out when the resource tracker gets disabled.
1266 //resourcemacros
1268 #define NOBUG_RESOURCE_HANDLE(handle) \
1269 NOBUG_IF_ALPHA(struct nobug_resource_record* handle)
1271 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1273 #define NOBUG_RESOURCE_USER(handle) \
1274 NOBUG_IF_ALPHA(struct nobug_resource_user* handle)
1276 #define NOBUG_RESOURCE_USER_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1280 //resourcemacros PARA RESOURCE_ANNOUNCE; RESOURCE_ANNOUNCE; publish new resources
1281 //resourcemacros
1282 //resourcemacros RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
1283 //resourcemacros NOBUG_RESOURCE_ANNOUNCE_RAW(flagptr, type, name, ptr, handle)
1284 //resourcemacros NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flagptr, type, name,
1285 //resourcemacros ptr, handle, context)
1286 //resourcemacros
1287 //resourcemacros Publishes resources.
1288 //resourcemacros
1289 //resourcemacros `flag`::
1290 //resourcemacros the NoBug flag name which turns logging on for this macro
1291 //resourcemacros `type`::
1292 //resourcemacros a string which should denote the domain of the resource,
1293 //resourcemacros examples are "file", "mutex", "lock", "database" and so on
1294 //resourcemacros `name`::
1295 //resourcemacros the actual name of a named resource this as string which
1296 //resourcemacros together with type forms a unique identifier of the resource. `type` and
1297 //resourcemacros `name` must be available through the entire lifetime of the resource, using
1298 //resourcemacros literal strings is recommended
1299 //resourcemacros `identifier`::
1300 //resourcemacros a pointer which should be unique for this resource, any
1301 //resourcemacros kind of pointer will suffice, it is only used for identification. In
1302 //resourcemacros multithreaded applications the thread identifier becomes an additional
1303 //resourcemacros identifier
1304 //resourcemacros `handle`::
1305 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to point to
1306 //resourcemacros the newly created resource.
1307 //resourcemacros
1308 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
1309 //resourcemacros announced more than one time.
1310 //resourcemacros
1311 //resourcemacros 'RESOURCE_ANNOUNCE()' acts like the head of a C loop statement, it ties to the following
1312 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1313 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1314 //resourcemacros
1316 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
1317 NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(&NOBUG_FLAG(flag), type, name, ptr, handle, NOBUG_CONTEXT)
1320 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
1321 NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, NOBUG_CONTEXT)
1324 #define NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, context) \
1325 NOBUG_IF_NOT_RELEASE( for ( \
1326 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1327 ({ \
1328 NOBUG_REQUIRE_CTX(!handle, context, "Announced resource handle not initialized"); \
1329 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1330 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1331 "RESOURCE_ANNOUNCE", context, \
1332 "%s: %s@%p", type, name, ptr);) \
1333 NOBUG_IF_ALPHA ( \
1334 NOBUG_RESOURCE_ASSERT_CTX(handle = nobug_resource_announce (type, name, \
1335 (const void*)ptr, \
1336 context), \
1337 "RESOURCE_ASSERT_ANNOUNCE", context, \
1338 "%s: %s@%p %s", type, name, ptr, nobug_resource_error); \
1340 1; \
1341 }); \
1342 section_; \
1343 ({ \
1344 NOBUG_IF_ALPHA (nobug_resource_announce_complete ();) \
1345 section_ = 0; \
1346 })))
1350 //resourcemacros PARA RESOURCE_FORGET; RESOURCE_FORGET; remove resources
1351 //resourcemacros
1352 //resourcemacros RESOURCE_FORGET(flag, handle)
1353 //resourcemacros NOBUG_RESOURCE_FORGET_RAW(flagptr, handle)
1354 //resourcemacros NOBUG_RESOURCE_FORGET_RAW_CTX(flagptr, handle, context)
1355 //resourcemacros
1356 //resourcemacros Removes resources that have become unavailable from the registry.
1357 //resourcemacros
1358 //resourcemacros `flag`::
1359 //resourcemacros the NoBug flag which turns logging on for this macro
1360 //resourcemacros `handle`::
1361 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1362 //resourcemacros
1363 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1364 //resourcemacros error is raised.
1365 //resourcemacros
1366 //resourcemacros 'RESOURCE_FORGET()' acts like the head of a C loop statement, it ties to the following
1367 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1368 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1369 //resourcemacros
1371 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1372 NOBUG_RESOURCE_FORGET_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1374 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1375 NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1377 #define NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, context) \
1378 NOBUG_IF_NOT_RELEASE( for ( \
1379 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1380 ({ \
1381 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1382 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1383 "RESOURCE_FORGET", context, "%s: %s@%p", \
1384 (handle)?(handle)->type:"", \
1385 (handle)?(handle)->hdr.name:"", \
1386 (handle)?(handle)->object_id:NULL);) \
1387 1; \
1388 }); \
1389 section_; \
1390 ({ \
1391 NOBUG_IF_ALPHA ( \
1392 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_forget (handle), \
1393 "RESOURCE_ASSERT_FORGET", context, "%s: %s@%p: %s", \
1394 (handle)?(handle)->type:"", \
1395 (handle)?(handle)->hdr.name:"", \
1396 (handle)?(handle)->object_id:NULL, \
1397 nobug_resource_error); \
1398 handle = NULL;) \
1399 section_ = 0; \
1400 }) \
1405 //resourcemacros PARA RESOURCE_RESETALL; RESOURCE_RESETALL; reset the resource tracker to a pristine state
1406 //resourcemacros
1407 //resourcemacros RESOURCE_RESETALL(flag)
1408 //resourcemacros NOBUG_RESOURCE_RESETALL_RAW(flagptr)
1409 //resourcemacros NOBUG_RESOURCE_RESETALL_RAW_CTX(flagptr, context)
1410 //resourcemacros
1411 //resourcemacros Sometimes the resource tracker can give false positives when it finds a locking order violation
1412 //resourcemacros while the programmer knows that this will never happen in the real program, because for example
1413 //resourcemacros this is only used at initialization or shutdown and never overlaps. This macro can then be used
1414 //resourcemacros to reset all whats learnt about all resources and start over.
1415 //resourcemacros
1416 //resourcemacros `flag`::
1417 //resourcemacros the NoBug flag which turns logging on for this macro
1418 //resourcemacros
1420 #define NOBUG_RESOURCE_RESETALL(flag) \
1421 NOBUG_RESOURCE_RESETALL_RAW_CTX(&NOBUG_FLAG(flag), NOBUG_CONTEXT)
1423 #define NOBUG_RESOURCE_RESETALL_RAW(flag) \
1424 NOBUG_RESOURCE_RESETALL_RAW_CTX(flag, NOBUG_CONTEXT)
1426 #define NOBUG_RESOURCE_RESETALL_RAW_CTX(flag, context) \
1427 NOBUG_IF_ALPHA ( \
1428 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_resetall (), \
1429 "RESOURCE_ASSERT_RESETALL", context, "%s", \
1430 nobug_resource_error))
1435 //resourcemacros PARA RESOURCE_RESET; RESOURCE_RESET; reset a single resource to a pristine state
1436 //resourcemacros
1437 //resourcemacros RESOURCE_RESET(flag, handle)
1438 //resourcemacros NOBUG_RESOURCE_RESETALL_RAW(flagptr, handle)
1439 //resourcemacros NOBUG_RESOURCE_RESETALL_RAW_CTX(flagptr, handle, context)
1440 //resourcemacros
1441 //resourcemacros Sometimes the resource tracker can give false positives when it finds a locking order violation
1442 //resourcemacros while the programmer knows that this will never happen in the real program, because for example
1443 //resourcemacros this is only used at initialization or shutdown and never overlaps. This macro can then be used
1444 //resourcemacros to reset all whats learnt about a single resources and start over.
1445 //resourcemacros
1446 //resourcemacros `flag`::
1447 //resourcemacros the NoBug flag which turns logging on for this macro
1448 //resourcemacros `handle`::
1449 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1450 //resourcemacros
1452 #define NOBUG_RESOURCE_RESET(flag, handle) \
1453 NOBUG_RESOURCE_RESET_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1455 #define NOBUG_RESOURCE_RESET_RAW(flag, handle) \
1456 NOBUG_RESOURCE_RESET_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1458 #define NOBUG_RESOURCE_RESET_RAW_CTX(flag, handle, context) \
1459 NOBUG_IF_ALPHA ( \
1460 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_reset (handle), \
1461 "RESOURCE_ASSERT_RESET", context, \
1462 "%s: %s@%p: %s", \
1463 (handle)?(handle)->type:"", \
1464 (handle)?(handle)->hdr.name:"", \
1465 (handle)?(handle)->object_id:NULL, \
1466 nobug_resource_error))
1471 //resourcemacros PARA RESOURCE_ENTER; RESOURCE_ENTER; claim a resource
1472 //resourcemacros
1473 //resourcemacros RESOURCE_ENTER(flag, announced, user, state, handle)
1474 //resourcemacros NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state,
1475 //resourcemacros handle, context)
1476 //resourcemacros
1477 //resourcemacros Acquire a resource.
1478 //resourcemacros
1479 //resourcemacros `flag`::
1480 //resourcemacros nobug flag which turns logging on for this macro
1481 //resourcemacros `announced`::
1482 //resourcemacros the handle set by `RESOURCE_ANNOUNCE`
1483 //resourcemacros `user`::
1484 //resourcemacros a free-form identifier
1485 //resourcemacros `state`::
1486 //resourcemacros the state to enter
1487 //resourcemacros `handle`::
1488 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to the
1489 //resourcemacros entering node
1490 //resourcemacros
1491 //resourcemacros `RESOURCE_ENTER()` acts like the head of a C loop statement, it ties to the following
1492 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1493 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1494 //resourcemacros
1496 #define NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle) \
1497 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, NOBUG_CONTEXT)
1500 #define NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, context) \
1501 NOBUG_IF_NOT_RELEASE( for ( \
1502 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1503 ({ \
1504 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1505 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, \
1506 "RESOURCE_ENTER", context, \
1507 "%s: %s@%p: %s: %s", \
1508 (resource)?(resource)->type:"", \
1509 (resource)?(resource)->hdr.name:"", \
1510 (resource)?(resource)->object_id:NULL, \
1511 user, \
1512 nobug_resource_states[state]);) \
1513 NOBUG_IF_ALPHA ( \
1514 NOBUG_RESOURCE_ASSERT_CTX(handle = \
1515 nobug_resource_enter (resource, \
1516 user, state, \
1517 context), \
1518 "RESOURCE_ASSERT_ENTER", context, \
1519 "%s: %s@%p: %s: %s: %s", \
1520 (resource)?(resource)->type:"", \
1521 (resource)?(resource)->hdr.name:"", \
1522 (resource)?(resource)->object_id:NULL, \
1523 user, nobug_resource_states[state], \
1524 nobug_resource_error);) \
1525 1; \
1526 }); \
1527 section_; \
1528 section_ = 0 \
1532 //resourcemacros PARA RESOURCE_WAIT; RESOURCE_WAIT; wait for a resource to become available
1533 //resourcemacros
1534 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle)
1535 //resourcemacros NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context)
1536 //resourcemacros
1537 //resourcemacros This is just an alias for
1538 //resourcemacros
1539 //resourcemacros RESOURCE_ENTER(flag, resource, user,
1540 //resourcemacros NOBUG_RESOURCE_WAITING, handle)
1541 ///resourcemacros
1542 //resourcemacros .How to use it
1543 //resourcemacros [source,c]
1544 //resourcemacros ----
1545 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle);
1546 //resourcemacros if (lock_my_resource() == ERROR)
1547 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle);
1548 //resourcemacros else
1549 //resourcemacros RESOURCE_STATE(flag, NOBUG_RESOURCE_EXCLUSIVE, handle);
1550 //resourcemacros ----
1551 //resourcemacros
1552 #define NOBUG_RESOURCE_WAIT(flag, resource, user, handle) \
1553 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1555 #define NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context) \
1556 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_WAITING, handle, context)
1559 //resourcemacros PARA RESOURCE_TRY; RESOURCE_TRY; wait for a resource to become available
1560 //resourcemacros
1561 //resourcemacros RESOURCE_TRY(flag, resource, user, handle)
1562 //resourcemacros NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context)
1563 //resourcemacros
1564 //resourcemacros This is just an alias for
1565 //resourcemacros
1566 //resourcemacros RESOURCE_ENTER(flag, resource, user,
1567 //resourcemacros NOBUG_RESOURCE_TRYING, handle)
1568 //resourcemacros
1569 //resourcemacros Trying on a resource is similar to waiting but will not trigger a deadlock check. This can be used
1570 //resourcemacros when a deadlock is expected at runtime and one handles this otherwise (by a timed wait or something like that).
1571 //resourcemacros
1572 #define NOBUG_RESOURCE_TRY(flag, resource, user, handle) \
1573 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_TRYING, handle)
1575 #define NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context) \
1576 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_TRYING, handle, context)
1580 //resourcemacros PARA RESOURCE_STATE; RESOURCE_STATE; change the state of a resource
1581 //resourcemacros
1582 //resourcemacros RESOURCE_STATE(flag, entered, state)
1583 //resourcemacros NOBUG_RESOURCE_STATE_CTX(flag, state, entered, context)
1584 //resourcemacros NOBUG_RESOURCE_STATE_RAW(flagptr, state, entered)
1585 //resourcemacros NOBUG_RESOURCE_STATE_RAW_CTX(flagptr, nstate, entered, context)
1586 //resourcemacros
1587 //resourcemacros Changes resource's state.
1588 //resourcemacros
1589 //resourcemacros `flag`::
1590 //resourcemacros is nobug flag which turns logging on for this macro
1591 //resourcemacros `state`::
1592 //resourcemacros the new state Note that only certain state transitions are
1593 //resourcemacros allowed, see discussion/diagram above
1594 //resourcemacros `entered`::
1595 //resourcemacros the handle set by `RESOURCE_ENTER`
1596 //resourcemacros
1597 //resourcemacros `RESOURCE_STATE()` acts like the head of a C loop statement, it ties to the following
1598 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1599 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1600 //resourcemacros
1602 #define NOBUG_RESOURCE_STATE(flag, state, entered) \
1603 NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, NOBUG_CONTEXT)
1605 #define NOBUG_RESOURCE_STATE_CTX(flag, state, entered, context) \
1606 NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, context)
1608 #define NOBUG_RESOURCE_STATE_RAW(flag, state, entered) \
1609 NOBUG_RESOURCE_STATE_RAW_CTX(flag, state, entered, NOBUG_CONTEXT)
1611 #define NOBUG_RESOURCE_STATE_RAW_CTX(flag, nstate, entered, context) \
1612 NOBUG_IF_NOT_RELEASE( for ( \
1613 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1614 ({ \
1615 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1616 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1617 "RESOURCE_STATE", context, \
1618 "%s: %s@%p: %s: %s->%s", \
1619 (entered)?(entered)->current->resource->type:"", \
1620 (entered)?(entered)->current->resource->hdr.name:"", \
1621 (entered)?(entered)->current->resource->object_id:"", \
1622 (entered)?(entered)->hdr.name:"", \
1623 nobug_resource_states[(entered)?(entered)->state \
1624 :NOBUG_RESOURCE_INVALID], \
1625 nobug_resource_states[nstate]); \
1627 NOBUG_IF_ALPHA( \
1628 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_state ((entered), nstate), \
1629 "RESOURCE_ASSERT_STATE", context, \
1630 "%s: %s@%p: %s: %s->%s: %s", \
1631 (entered)?(entered)->current->resource->type:"", \
1632 (entered)?(entered)->current->resource->hdr.name:"", \
1633 (entered)?(entered)->current->resource->object_id:"", \
1634 (entered)?(entered)->hdr.name:"", \
1635 nobug_resource_states[(entered)?(entered)->state \
1636 :NOBUG_RESOURCE_INVALID], \
1637 nobug_resource_states[nstate], \
1638 nobug_resource_error); \
1640 1; \
1641 }); \
1642 section_; \
1643 section_ = 0))
1646 //resourcemacros PARA RESOURCE_LEAVE; RESOURCE_LEAVE; relinquish a claimed resource
1647 //resourcemacros
1648 //resourcemacros RESOURCE_LEAVE(flag, handle){}
1649 //resourcemacros NOBUG_RESOURCE_LEAVE_RAW(flagptr, handle){}
1650 //resourcemacros NOBUG_RESOURCE_LEAVE_RAW_CTX(flagptr, handle, context){}
1651 //resourcemacros
1652 //resourcemacros Disconnect from a resource identified with its handle.
1653 //resourcemacros
1654 //resourcemacros `flag`::
1655 //resourcemacros nobug flag which turns logging on for this macro
1656 //resourcemacros `handle`::
1657 //resourcemacros the handle you got while entering the resource
1658 //resourcemacros
1659 //resourcemacros `RESOURCE_LEAVE()` acts like the head of a C loop statement, it ties to the following
1660 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1661 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1662 //resourcemacros
1663 //resourcemacros .How to use it
1664 //resourcemacros [source,c]
1665 //resourcemacros ----
1666 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle)
1667 //resourcemacros {
1668 //resourcemacros unlock_my_resource();
1669 //resourcemacros }
1670 //resourcemacros ----
1671 //resourcemacros
1673 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1674 NOBUG_RESOURCE_LEAVE_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1676 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1677 NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1679 #define NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, context) \
1680 NOBUG_IF_NOT_RELEASE( \
1681 for ( \
1682 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = ({ \
1683 nobug_resource_leave_pre(); \
1684 1; \
1685 }); \
1686 section_; \
1687 ({ \
1688 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1689 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1690 "RESOURCE_LEAVE", context, \
1691 "%s: %s@%p: %s: %s", \
1692 (handle)?(handle)->current->resource->type:"", \
1693 (handle)?(handle)->current->resource->hdr.name:"", \
1694 (handle)?(handle)->current->resource->object_id:"", \
1695 (handle)?(handle)->hdr.name:"", \
1696 nobug_resource_states[(handle)?(handle)->state \
1697 :NOBUG_RESOURCE_INVALID]); \
1699 NOBUG_IF_ALPHA( \
1700 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_leave (handle), \
1701 "RESOURCE_ASSERT_LEAVE", context, \
1702 "%s: %s@%p: %s: %s: %s", \
1703 (handle)?(handle)->current->resource->type:"", \
1704 (handle)?(handle)->current->resource->hdr.name:"", \
1705 (handle)?(handle)->current->resource->object_id:"", \
1706 (handle)?(handle)->hdr.name:"", \
1707 nobug_resource_states[(handle)?(handle)->state \
1708 :NOBUG_RESOURCE_INVALID], \
1709 nobug_resource_error); \
1710 handle = NULL; \
1712 section_ = 0; \
1713 })))
1716 //resourcemacros PARA RESOURCE_ASSERT_STATE; RESOURCE_ASSERT_STATE; assert the state of a resource
1717 //resourcemacros
1718 //resourcemacros RESOURCE_ASSERT_STATE(resource, state)
1719 //resourcemacros RESOURCE_ASSERT_STATE_IF(when, resource, state)
1720 //resourcemacros NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context)
1721 //resourcemacros NOBUG_RESOURCE_ASSERT_STATE_IF_CTX(when, resource,
1722 //resourcemacros state, context)
1723 //resourcemacros
1724 //resourcemacros Assert that we have a resource in a given state. For multithreaded programms the topmost
1725 //resourcemacros state of the calling thread is checked, for non threadeded programs the most recent state on
1726 //resourcemacros resource is used.
1727 //resourcemacros
1728 //resourcemacros `when`::
1729 //resourcemacros Condition which must be true for testing the assertion
1730 //resourcemacros `resource`::
1731 //resourcemacros Resource handle
1732 //resourcemacros `state`::
1733 //resourcemacros The expected state
1734 //resourcemacros
1736 #define NOBUG_RESOURCE_ASSERT_STATE(resource, state) \
1737 NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, NOBUG_CONTEXT)
1739 #define NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context) \
1740 NOBUG_IF_ALPHA( \
1741 do { \
1742 enum nobug_resource_state mystate = nobug_resource_mystate (resource); \
1743 NOBUG_RESOURCE_ASSERT_CTX(mystate == state, \
1744 "RESOURCE_ASSERT_STATE", context, \
1745 "resource %p has state %s but %s was expected", \
1746 resource, nobug_resource_states[mystate], nobug_resource_states[state]); \
1747 } while (0))
1750 #define NOBUG_RESOURCE_ASSERT_STATE_IF(when, resource, state) \
1751 NOBUG_WHEN(when, NOBUG_RESOURCE_ASSERT_STATE (resource, state))
1754 /* assertion which dumps all resources */
1755 #define NOBUG_RESOURCE_ASSERT_CTX(expr, what, context, ...) \
1756 NOBUG_IF_ALPHA( \
1757 NOBUG_WHEN (!(expr), \
1758 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
1759 what, context, \
1760 ""__VA_ARGS__); \
1761 nobug_resource_dump_all (NOBUG_RESOURCE_DUMP_CONTEXT( \
1762 &nobug_flag_NOBUG_ON, \
1763 LOG_EMERG, \
1764 context)); \
1765 NOBUG_BACKTRACE_CTX(context); \
1766 NOBUG_ABORT))
1770 //resourcemacros PARA RESOURCE_DUMP; RESOURCE_DUMP; dump the state of a single resource
1771 //resourcemacros
1772 //resourcemacros NOBUG_RESOURCE_DUMP(flag, handle)
1773 //resourcemacros NOBUG_RESOURCE_DUMP_IF(when, flag, handle)
1774 //resourcemacros
1775 //resourcemacros Dump the state of a single resource.
1776 //resourcemacros
1777 //resourcemacros `when`::
1778 //resourcemacros Condition which must be true to dump the resource
1779 //resourcemacros `flag`::
1780 //resourcemacros Nobug flag for the log channel
1781 //resourcemacros `handle`::
1782 //resourcemacros handle of the resource to be dumped
1783 //resourcemacros
1785 #define NOBUG_RESOURCE_DUMP(flag, handle) \
1786 NOBUG_IF_ALPHA( \
1787 do { \
1788 nobug_resource_dump (handle, NOBUG_RESOURCE_DUMP_CONTEXT( \
1789 &NOBUG_FLAG(flag), \
1790 NOBUG_RESOURCE_LOG_LEVEL, \
1791 NOBUG_CONTEXT)); \
1792 } while (0))
1794 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle) \
1795 NOBUG_IF_ALPHA( \
1796 NOBUG_WHEN(when, \
1797 nobug_resource_dump (handle, NOBUG_RESOURCE_DUMP_CONTEXT( \
1798 &NOBUG_FLAG(flag), \
1799 NOBUG_RESOURCE_LOG_LEVEL, \
1800 NOBUG_CONTEXT)); \
1805 //resourcemacros PARA RESOURCE_DUMPALL; RESOURCE_DUMPALL; dump the state of all resources
1806 //resourcemacros
1807 //resourcemacros NOBUG_RESOURCE_DUMPALL(flag)
1808 //resourcemacros NOBUG_RESOURCE_DUMPALL_IF(when, flag)
1809 //resourcemacros
1810 //resourcemacros Dump the state of all resources.
1811 //resourcemacros
1812 //resourcemacros `when`::
1813 //resourcemacros Condition which must be true to dump the resources
1814 //resourcemacros `flag`::
1815 //resourcemacros Nobug flag for the log channel
1816 //resourcemacros
1818 #define NOBUG_RESOURCE_DUMPALL(flag) \
1819 NOBUG_IF_ALPHA( \
1820 do { \
1821 nobug_resource_dump_all (NOBUG_RESOURCE_DUMP_CONTEXT( \
1822 &NOBUG_FLAG(flag), \
1823 NOBUG_RESOURCE_LOG_LEVEL, \
1824 NOBUG_CONTEXT)); \
1825 } while (0))
1828 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag) \
1829 NOBUG_IF_ALPHA( \
1830 NOBUG_WHEN(when, \
1831 nobug_resource_dump_all (NOBUG_RESOURCE_DUMP_CONTEXT( \
1832 &NOBUG_FLAG(flag), \
1833 NOBUG_RESOURCE_LOG_LEVEL, \
1834 NOBUG_CONTEXT)); \
1838 //resourcemacros PARA RESOURCE_LIST; RESOURCE_LIST; enumerate all registered resources
1839 //resourcemacros
1840 //resourcemacros NOBUG_RESOURCE_LIST(flag)
1841 //resourcemacros NOBUG_RESOURCE_LIST_IF(when, flag)
1842 //resourcemacros
1843 //resourcemacros List all registered resources.
1844 //resourcemacros
1845 //resourcemacros `when`::
1846 //resourcemacros Condition which must be true to list the resources
1847 //resourcemacros `flag`::
1848 //resourcemacros Nobug flag for the log channel
1849 //resourcemacros
1851 #define NOBUG_RESOURCE_LIST(flag) \
1852 NOBUG_IF_ALPHA( \
1853 do { \
1854 nobug_resource_list (NOBUG_RESOURCE_DUMP_CONTEXT( \
1855 &NOBUG_FLAG(flag), \
1856 NOBUG_RESOURCE_LOG_LEVEL, \
1857 NOBUG_CONTEXT)); \
1858 } while (0))
1861 #define NOBUG_RESOURCE_LIST_IF(when, flag) \
1862 NOBUG_IF_ALPHA( \
1863 NOBUG_WHEN(when, \
1864 nobug_resource_list (NOBUG_RESOURCE_DUMP_CONTEXT( \
1865 &NOBUG_FLAG(flag), \
1866 NOBUG_RESOURCE_LOG_LEVEL, \
1867 NOBUG_CONTEXT)); \
1871 /* constructing a resource-dump context */
1872 #ifndef __cplusplus
1873 #define NOBUG_RESOURCE_DUMP_CONTEXT(flag, level, context) \
1874 ((struct nobug_resource_dump_context){ \
1875 flag, \
1876 level, \
1877 context})
1878 #else
1879 #define NOBUG_CONTEXT (nobug_context(__FILE__, __LINE__, NOBUG_FUNC))
1880 #define NOBUG_RESOURCE_DUMP_CONTEXT(flag, level, context) \
1881 (nobug_resource_dump_context(flag, level, context))
1882 #endif
1886 threading support
1888 #if NOBUG_USE_PTHREAD
1889 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1890 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1892 #else
1893 #define NOBUG_THREAD_ID_SET(name)
1894 #define NOBUG_THREAD_ID_GET ""
1895 #endif
1897 #define NOBUG_THREAD_DATA (*nobug_thread_data())
1901 Debuggers
1904 #define NOBUG_DBG_NONE 0
1905 #define NOBUG_DBG_GDB 1
1906 #define NOBUG_DBG_VALGRIND 2
1908 #define NOBUG_ACTIVE_DBG \
1909 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1910 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1913 //toolmacros HEAD- Tool Macros;;
1914 //toolmacros
1915 //toolmacros PARA NOBUG_FLAG_RAW; NOBUG_FLAG_RAW; pass direct flag pointer
1916 //toolmacros
1917 //toolmacros NOBUG_FLAG_RAW(ptr)
1918 //toolmacros
1919 //toolmacros Using this macro one can pass a direct pointer to a flag where a name would
1920 //toolmacros be expected. This is sometimes convinient when flag pointers are passed around
1921 //toolmacros in management strutures and one wants to tie logging to dynamic targets.
1922 //toolmacros
1923 //toolmacros [source,c]
1924 //toolmacros ----
1925 //toolmacros NOBUG_DEFINE_FLAG(myflag);
1926 //toolmacros ...
1927 //toolmacros struct nobug_flag* ptr = &NOBUG_FLAG(myflag);
1928 //toolmacros TRACE(NOBUG_FLAG_RAW(ptr), "Passed flag by pointer")
1929 //toolmacros ----
1930 //toolmacros
1932 #define nobug_flag_NOBUG_FLAG_RAW(name) *name
1935 //toolmacros PARA Backtraces; BACKTRACE; generate a backtrace
1936 //toolmacros
1937 //toolmacros BACKTRACE
1938 //toolmacros NOBUG_BACKTRACE_CTX(context)
1939 //toolmacros
1940 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1941 //toolmacros This is automatically called when NoBug finds an error and is due
1942 //toolmacros to abort. But one might call it manually too.
1943 //toolmacros
1945 #define NOBUG_BACKTRACE NOBUG_BACKTRACE_CTX(NOBUG_CONTEXT)
1947 #define NOBUG_BACKTRACE_CTX(context) \
1948 NOBUG_IF_ALPHA( \
1949 switch (NOBUG_ACTIVE_DBG) { \
1950 case NOBUG_DBG_VALGRIND: \
1951 NOBUG_BACKTRACE_VALGRIND(context); \
1952 break; \
1953 default: \
1954 NOBUG_BACKTRACE_GLIBC(context); \
1955 }) \
1956 NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC(context))
1958 #define NOBUG_BACKTRACE_GDB(context) UNIMPLEMENTED
1960 #define NOBUG_BACKTRACE_VALGRIND(context) \
1961 NOBUG_IF(NOBUG_USE_VALGRIND, \
1962 nobug_backtrace_valgrind (context) \
1966 #ifndef NOBUG_BACKTRACE_DEPTH
1967 #define NOBUG_BACKTRACE_DEPTH 256
1968 #endif
1970 #define NOBUG_BACKTRACE_GLIBC(context) \
1971 NOBUG_IF_NOT_RELEASE( \
1972 NOBUG_IF(NOBUG_USE_EXECINFO, do { \
1973 nobug_backtrace_glibc (context); \
1974 } while (0)))
1977 #ifndef NOBUG_TAB
1978 #define NOBUG_TAB " "
1979 #endif
1981 //toolmacros PARA Aborting; ABORT; abort the program
1982 //toolmacros
1983 //toolmacros NOBUG_ABORT_
1984 //toolmacros
1985 //toolmacros This is the default implementation for aborting the program, it first syncs all ringbuffers to disk, then
1986 //toolmacros calls the abort callback if defined and then `abort()`.
1987 //toolmacros
1988 //toolmacros NOBUG_ABORT
1989 //toolmacros
1990 //toolmacros If not overridden, evaluates to `NOBUG_ABORT_`. One can override this before including
1991 //toolmacros `nobug.h` to customize abortion behaviour. This will be local to the translation unit then.
1992 //toolmacros
1993 #ifndef NOBUG_ABORT
1994 #define NOBUG_ABORT NOBUG_ABORT_
1995 #endif
1997 #define NOBUG_ABORT_ \
1998 do { \
1999 nobug_ringbuffer_allsync (); \
2000 if (nobug_abort_callback) \
2001 nobug_abort_callback (nobug_callback_data); \
2002 abort(); \
2003 } while(0)
2007 init and other function wrapers
2009 #define NOBUG_INIT nobug_init(NOBUG_CONTEXT)
2012 short macros without NOBUG_
2014 #ifndef NOBUG_DISABLE_SHORTNAMES
2015 #ifndef REQUIRE
2016 #define REQUIRE NOBUG_REQUIRE
2017 #endif
2018 #ifndef REQUIRE_IF
2019 #define REQUIRE_IF NOBUG_REQUIRE_IF
2020 #endif
2021 #ifndef ENSURE
2022 #define ENSURE NOBUG_ENSURE
2023 #endif
2024 #ifndef ENSURE_IF
2025 #define ENSURE_IF NOBUG_ENSURE_IF
2026 #endif
2027 #ifndef ASSERT
2028 #define ASSERT NOBUG_ASSERT
2029 #endif
2030 #ifndef ASSERT_IF
2031 #define ASSERT_IF NOBUG_ASSERT_IF
2032 #endif
2033 #ifndef CHECK
2034 #define CHECK NOBUG_CHECK
2035 #endif
2036 #ifndef CHECK
2037 #define CHECK NOBUG_CHECK
2038 #endif
2039 #ifndef INVARIANT
2040 #define INVARIANT NOBUG_INVARIANT
2041 #endif
2042 #ifndef INVARIANT_IF
2043 #define INVARIANT_IF NOBUG_INVARIANT_IF
2044 #endif
2045 #ifndef INVARIANT_ASSERT
2046 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
2047 #endif
2048 #ifndef INVARIANT_ASSERT_IF
2049 #define INVARIANT_ASSERT_IF NOBUG_INVARIANT_ASSERT_IF
2050 #endif
2051 #ifndef DUMP
2052 #define DUMP NOBUG_DUMP
2053 #endif
2054 #ifndef DUMP_IF
2055 #define DUMP_IF NOBUG_DUMP_IF
2056 #endif
2057 #ifndef DUMP_LOG
2058 #define DUMP_LOG NOBUG_DUMP_LOG
2059 #endif
2060 #ifndef DUMP_LOG_IF
2061 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
2062 #endif
2063 #ifndef LOG
2064 #define LOG NOBUG_LOG
2065 #endif
2066 #ifndef LOG_IF
2067 #define LOG_IF NOBUG_LOG_IF
2068 #endif
2069 #ifndef ECHO
2070 #define ECHO NOBUG_ECHO
2071 #endif
2072 #ifndef ALERT
2073 #define ALERT NOBUG_ALERT
2074 #endif
2075 #ifndef ALERT_IF
2076 #define ALERT_IF NOBUG_ALERT_IF
2077 #endif
2078 #ifndef CRITICAL
2079 #define CRITICAL NOBUG_CRITICAL
2080 #endif
2081 #ifndef CRITICAL_IF
2082 #define CRITICAL_IF NOBUG_CRITICAL_IF
2083 #endif
2084 #ifndef ERROR
2085 #define ERROR NOBUG_ERROR
2086 #endif
2087 #ifndef ERROR_IF
2088 #define ERROR_IF NOBUG_ERROR_IF
2089 #endif
2090 #ifndef WARN
2091 #define WARN NOBUG_WARN
2092 #endif
2093 #ifndef WARN_IF
2094 #define WARN_IF NOBUG_WARN_IF
2095 #endif
2096 #ifndef INFO
2097 #define INFO NOBUG_INFO
2098 #endif
2099 #ifndef INFO_IF
2100 #define INFO_IF NOBUG_INFO_IF
2101 #endif
2102 #ifndef NOTICE
2103 #define NOTICE NOBUG_NOTICE
2104 #endif
2105 #ifndef NOTICE_IF
2106 #define NOTICE_IF NOBUG_NOTICE_IF
2107 #endif
2108 #ifndef TRACE
2109 #define TRACE NOBUG_TRACE
2110 #endif
2111 #ifndef TRACE_IF
2112 #define TRACE_IF NOBUG_TRACE_IF
2113 #endif
2114 #ifndef BACKTRACE
2115 #define BACKTRACE NOBUG_BACKTRACE
2116 #endif
2117 #ifndef DEPRECATED
2118 #define DEPRECATED NOBUG_DEPRECATED
2119 #endif
2120 #ifndef UNIMPLEMENTED
2121 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
2122 #endif
2123 #ifndef FIXME
2124 #define FIXME NOBUG_FIXME
2125 #endif
2126 #ifndef TODO
2127 #define TODO NOBUG_TODO
2128 #endif
2129 #ifndef PLANNED
2130 #define PLANNED NOBUG_PLANNED
2131 #endif
2132 #ifndef NOTREACHED
2133 #define NOTREACHED NOBUG_NOTREACHED
2134 #endif
2135 #ifndef ELSE_NOTREACHED
2136 #define ELSE_NOTREACHED NOBUG_ELSE_NOTREACHED
2137 #endif
2138 #ifndef INJECT_GOODBAD
2139 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
2140 #endif
2141 #ifndef INJECT_FAULT
2142 #define INJECT_FAULT NOBUG_INJECT_FAULT
2143 #endif
2144 #ifndef COVERAGE_DISABLE
2145 #define COVERAGE_DISABLE NOBUG_COVERAGE_DISABLE
2146 #endif
2147 #ifndef COVERAGE_ENABLE
2148 #define COVERAGE_ENABLE NOBUG_COVERAGE_ENABLE
2149 #endif
2150 #ifndef COVERAGE_FAULT
2151 #define COVERAGE_FAULT NOBUG_COVERAGE_FAULT
2152 #endif
2153 #ifndef COVERAGE_GOODBAD
2154 #define COVERAGE_GOODBAD NOBUG_COVERAGE_GOODBAD
2155 #endif
2156 #ifndef CLEANUP
2157 #define CLEANUP NOBUG_CLEANUP
2158 #endif
2159 #ifndef CHECKED
2160 #define CHECKED NOBUG_CHECKED
2161 #endif
2162 #ifndef UNCHECKED
2163 #define UNCHECKED NOBUG_UNCHECKED
2164 #endif
2165 #ifndef RESOURCE_ANNOUNCE
2166 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
2167 #endif
2168 #ifndef RESOURCE_FORGET
2169 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
2170 #endif
2171 #ifndef RESOURCE_RESETALL
2172 #define RESOURCE_RESETALL NOBUG_RESOURCE_RESETALL
2173 #endif
2174 #ifndef RESOURCE_RESET
2175 #define RESOURCE_RESET NOBUG_RESOURCE_RESET
2176 #endif
2177 #ifndef RESOURCE_ENTER
2178 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
2179 #endif
2180 #ifndef RESOURCE_WAIT
2181 #define RESOURCE_WAIT NOBUG_RESOURCE_WAIT
2182 #endif
2183 #ifndef RESOURCE_TRY
2184 #define RESOURCE_TRY NOBUG_RESOURCE_TRY
2185 #endif
2186 #ifndef RESOURCE_STATE
2187 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
2188 #endif
2189 #ifndef RESOURCE_LEAVE
2190 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
2191 #endif
2192 #ifndef RESOURCE_LEAVE_LOOKUP
2193 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
2194 #endif
2195 #ifndef RESOURCE_HANDLE
2196 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
2197 #endif
2198 #ifndef RESOURCE_HANDLE_INIT
2199 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
2200 #endif
2201 #ifndef RESOURCE_USER
2202 #define RESOURCE_USER NOBUG_RESOURCE_USER
2203 #endif
2204 #ifndef RESOURCE_ASSERT_STATE
2205 #define RESOURCE_ASSERT_STATE NOBUG_RESOURCE_ASSERT_STATE
2206 #endif
2207 #ifndef RESOURCE_ASSERT_STATE_IF
2208 #define RESOURCE_ASSERT_STATE_IF NOBUG_RESOURCE_ASSERT_STATE_IF
2209 #endif
2210 #ifndef RESOURCE_USER_INIT
2211 #define RESOURCE_USER_INIT NOBUG_RESOURCE_USER_INIT
2212 #endif
2213 #ifndef RESOURCE_DUMP
2214 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
2215 #endif
2216 #ifndef RESOURCE_DUMP_IF
2217 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
2218 #endif
2219 #ifndef RESOURCE_DUMPALL
2220 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
2221 #endif
2222 #ifndef RESOURCE_DUMPALL_IF
2223 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
2224 #endif
2225 #ifndef RESOURCE_LIST
2226 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
2227 #endif
2228 #ifndef RESOURCE_LIST_IF
2229 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
2230 #endif
2231 #endif /* NOBUG_DISABLE_SHORTNAMES */
2235 Tool macros
2237 #ifdef __GNUC__
2238 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
2239 #define NOBUG_ATTR_PRINTF(fmt, ell) __attribute__ ((format (printf, fmt, ell)))
2240 #else
2241 #define NOBUG_CLEANUP(fn)
2242 #define NOBUG_ATTR_PRINTF(fmt, ell)
2243 #endif
2246 //toolmacros PARA NOBUG_ALPHA_COMMA; NOBUG_ALPHA_COMMA; append something after a comma in *ALPHA* builds
2247 //toolmacros
2248 //toolmacros NOBUG_ALPHA_COMMA(something)
2249 //toolmacros NOBUG_ALPHA_COMMA_NULL
2250 //toolmacros
2251 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
2252 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
2253 //toolmacros use this macros to append a comman and something else only in *ALPHA* builds as in:
2254 //toolmacros
2255 //toolmacros [source,C]
2256 //toolmacros ----
2257 //toolmacros struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
2258 //toolmacros ----
2259 //toolmacros
2261 #define NOBUG_COMMA ,
2262 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
2263 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
2265 #define NOBUG_ONCE(code) \
2266 do { \
2267 static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 1; \
2268 if (NOBUG_EXPECT_FALSE(NOBUG_CAT(nobug_once_,__LINE__))) \
2270 NOBUG_CAT(nobug_once_,__LINE__) = 0; \
2271 code; \
2273 } while (0)
2275 #if __GNUC__
2276 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
2277 #else
2278 #define NOBUG_EXPECT_FALSE(x) x
2279 #endif
2281 #define NOBUG_WHEN(when, ...) \
2282 do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
2285 //toolmacros PARA NOBUG_IF_*; NOBUG_IF; include code conditionally on build level
2286 //toolmacros
2287 //toolmacros NOBUG_IF_ALPHA(...)
2288 //toolmacros NOBUG_IF_NOT_ALPHA(...)
2289 //toolmacros NOBUG_IF_BETA(...)
2290 //toolmacros NOBUG_IF_NOT_BETA(...)
2291 //toolmacros NOBUG_IF_RELEASE(...)
2292 //toolmacros NOBUG_IF_NOT_RELEASE(...)
2293 //toolmacros
2294 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
2295 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
2296 //toolmacros internally, but can also be used for custom things.
2297 //toolmacros
2299 #define NOBUG_IF_ALPHA(...) \
2300 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__) \
2302 #define NOBUG_IF_NOT_ALPHA(...) \
2303 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__) \
2305 #define NOBUG_IF_BETA(...) \
2306 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__) \
2308 #define NOBUG_IF_NOT_BETA(...) \
2309 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__) \
2311 #define NOBUG_IF_RELEASE(...) \
2312 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__) \
2314 #define NOBUG_IF_NOT_RELEASE(...) \
2315 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__) \
2318 preprocessor hacks/metaprogramming
2321 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
2322 #define NOBUG_IF_1(...) __VA_ARGS__
2323 #define NOBUG_IF_0(...)
2325 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
2327 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
2328 #define NOBUG_NOT_1 0
2329 #define NOBUG_NOT_0 1
2331 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
2332 #define NOBUG_AND_00 0
2333 #define NOBUG_AND_01 0
2334 #define NOBUG_AND_10 0
2335 #define NOBUG_AND_11 1
2337 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
2338 #define NOBUG_OR_00 0
2339 #define NOBUG_OR_01 1
2340 #define NOBUG_OR_10 1
2341 #define NOBUG_OR_11 1
2343 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
2344 #define NOBUG_XOR_00 0
2345 #define NOBUG_XOR_01 1
2346 #define NOBUG_XOR_10 1
2347 #define NOBUG_XOR_11 0
2349 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
2350 #define NOBUG_CAT_(a,b) a##b
2352 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
2353 #define NOBUG_CAT3_(a,b,c) a##b##c
2355 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
2356 #define NOBUG_STRINGIZE_(s) #s
2360 LIBNOBUG DECLARATIONS
2362 #ifdef __cplusplus
2363 extern "C" {
2364 #elif 0
2365 } /* fix emacs indent */
2366 #endif
2368 #ifndef LLIST_DEFINED
2369 #define LLIST_DEFINED
2370 struct llist_struct
2372 struct llist_struct *next;
2373 struct llist_struct *prev;
2375 #endif
2378 source context
2381 struct nobug_context
2383 const char* file;
2384 int line;
2385 const char* func;
2387 #ifdef __cplusplus
2388 nobug_context (const char* file_, int line_, const char* func_)
2389 : file(file_), line(line_), func(func_) {}
2390 #endif
2393 const char*
2394 nobug_basename (const char* const file);
2397 envvar control
2399 enum nobug_log_targets
2401 NOBUG_TARGET_RINGBUFFER,
2402 NOBUG_TARGET_CONSOLE,
2403 NOBUG_TARGET_FILE,
2404 NOBUG_TARGET_SYSLOG,
2405 NOBUG_TARGET_APPLICATION
2408 struct nobug_flag
2410 const char* name;
2411 struct nobug_flag* parent;
2412 volatile int initialized;
2413 int limits[5];
2414 struct nobug_ringbuffer* ringbuffer_target;
2415 FILE* console_target;
2416 FILE* file_target;
2420 nobug_env_parse_flag (const char* env, struct nobug_flag* flag, int default_target, int default_limit, const struct nobug_context context);
2423 nobug_env_init_flag (struct nobug_flag* flag, int default_target, int default_limit, const struct nobug_context context);
2427 ringbuffer
2429 struct nobug_ringbuffer
2431 struct llist_struct node; /* all ringbufers are chained together, needed for sync */
2432 char* pos;
2433 char* start;
2434 size_t size;
2435 size_t guard;
2436 char name[256];
2439 enum nobug_ringbuffer_flags
2441 NOBUG_RINGBUFFER_DEFAULT, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
2442 NOBUG_RINGBUFFER_APPEND = 1, /* use existing backing file, append if possible */
2443 NOBUG_RINGBUFFER_TEMP = 2, /* unlink file instantly */
2444 NOBUG_RINGBUFFER_KEEP = 4 /* dont unlink the file at destroy */
2447 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
2448 with sane (but undefined) semantics.
2451 struct nobug_ringbuffer*
2452 nobug_ringbuffer_init (struct nobug_ringbuffer* self, size_t size,
2453 size_t guard, const char * name, int flags);
2455 struct nobug_ringbuffer*
2456 nobug_ringbuffer_new (size_t size, size_t guard, const char * name, int flags);
2458 struct nobug_ringbuffer*
2459 nobug_ringbuffer_destroy (struct nobug_ringbuffer* self);
2461 void
2462 nobug_ringbuffer_delete (struct nobug_ringbuffer* self);
2464 void
2465 nobug_ringbuffer_sync (struct nobug_ringbuffer* self);
2467 void
2468 nobug_ringbuffer_allsync (void);
2471 nobug_ringbuffer_vprintf (struct nobug_ringbuffer* self, const char* fmt, va_list ap);
2474 nobug_ringbuffer_printf (struct nobug_ringbuffer* self, const char* fmt, ...);
2476 char*
2477 nobug_ringbuffer_append (struct nobug_ringbuffer* self);
2480 nobug_ringbuffer_extend (struct nobug_ringbuffer* self, size_t newsize, const char fill);
2482 char*
2483 nobug_ringbuffer_prev (struct nobug_ringbuffer* self, char* pos);
2485 char*
2486 nobug_ringbuffer_next (struct nobug_ringbuffer* self, char* pos);
2489 nobug_ringbuffer_save (struct nobug_ringbuffer* self, FILE* out);
2492 nobug_ringbuffer_load (struct nobug_ringbuffer* self, FILE* in);
2494 char*
2495 nobug_ringbuffer_pos (struct nobug_ringbuffer* self);
2497 void
2498 nobug_ringbuffer_pop (struct nobug_ringbuffer* self);
2502 multithreading extras
2505 struct nobug_tls_data
2507 const char* thread_id;
2508 unsigned thread_num; /* thread counter at initialization, gives a unique thread number */
2509 unsigned thread_gen; /* incremented at each name reset, (currently unused) */
2510 void* data;
2511 struct llist_struct res_stack; /* resources of this thread */
2513 unsigned coverage_disable_cnt;
2516 extern pthread_key_t nobug_tls_key;
2518 struct nobug_tls_data*
2519 nobug_thread_set (const char* name);
2521 struct nobug_tls_data*
2522 nobug_thread_get (void);
2524 const char*
2525 nobug_thread_id_set (const char* name);
2527 const char*
2528 nobug_thread_id_get (void);
2530 #if NOBUG_USE_PTHREAD
2531 extern pthread_mutex_t nobug_logging_mutex;
2532 extern pthread_mutex_t nobug_resource_mutex;
2533 #endif
2535 void**
2536 nobug_thread_data (void);
2539 resource registry
2541 enum nobug_resource_state
2543 NOBUG_RESOURCE_INVALID,
2544 NOBUG_RESOURCE_WAITING,
2545 NOBUG_RESOURCE_TRYING,
2546 NOBUG_RESOURCE_EXCLUSIVE,
2547 NOBUG_RESOURCE_RECURSIVE,
2548 NOBUG_RESOURCE_SHARED
2552 struct nobug_resource_header
2554 struct llist_struct node; /* link node for resource registry or users */
2555 const char* name; /* name */
2556 struct nobug_context extra; /* context information */
2559 struct nobug_resource_node;
2560 struct nobug_resource_user;
2562 struct nobug_resource_record
2564 struct nobug_resource_header hdr;
2566 struct llist_struct users; /* list of users of this resource */
2567 const void* object_id; /* unique identifer, usually a this pointer or similar */
2568 const char* type; /* type */
2570 #if NOBUG_USE_PTHREAD
2571 struct llist_struct nodes;
2572 #endif
2576 struct nobug_resource_node
2578 struct llist_struct node; /* all nodes for one resource */
2580 struct nobug_resource_record* resource; /* backpointer */
2581 struct nobug_resource_node* parent; /* upwards the tree */
2583 struct llist_struct childs; /* down the tree, all nodes pointing to here (TODO make this a slist) */
2584 struct llist_struct cldnode; /* node to accumulate all childrens of a parent (TODO slist) */
2588 struct nobug_resource_user
2590 struct nobug_resource_header hdr;
2592 struct nobug_resource_node* current; /* this resource */
2593 enum nobug_resource_state state; /* state */
2595 #if NOBUG_USE_PTHREAD
2596 struct nobug_tls_data* thread; /* pointer to this theads id */
2597 struct llist_struct res_stack; /* resources of this thread */
2598 #endif
2602 extern const char* nobug_resource_error;
2604 extern const char* nobug_resource_states[];
2607 void
2608 nobug_resource_init (void);
2610 void
2611 nobug_resource_destroy (void);
2614 struct nobug_resource_record*
2615 nobug_resource_announce (const char* type, const char* name, const void* object_id, const struct nobug_context extra);
2617 void
2618 nobug_resource_announce_complete (void);
2621 nobug_resource_forget (struct nobug_resource_record* node);
2624 struct nobug_resource_user*
2625 nobug_resource_enter (struct nobug_resource_record* resource,
2626 const char* name,
2627 enum nobug_resource_state state,
2628 const struct nobug_context extra);
2632 nobug_resource_leave (struct nobug_resource_user* handle);
2635 void
2636 nobug_resource_leave_pre (void);
2639 unsigned
2640 nobug_resource_record_available (void);
2643 unsigned
2644 nobug_resource_user_available (void);
2647 #if NOBUG_USE_PTHREAD
2648 unsigned
2649 nobug_resource_node_available (void);
2650 #endif
2654 nobug_resource_reset (struct nobug_resource_record* self);
2658 nobug_resource_resetall (void);
2661 struct nobug_resource_dump_context
2663 struct nobug_flag* flag;
2664 int level;
2665 struct nobug_context ctx;
2667 #ifdef __cplusplus
2668 nobug_resource_dump_context (struct nobug_flag* flag_,
2669 int level_,
2670 struct nobug_context ctx_)
2671 : flag(flag_), level(level_), ctx(ctx_) {}
2672 #endif
2675 enum nobug_resource_state
2676 nobug_resource_mystate (struct nobug_resource_record* res);
2678 void
2679 nobug_resource_dump (struct nobug_resource_record* resource, const struct nobug_resource_dump_context context);
2681 void
2682 nobug_resource_dump_all (const struct nobug_resource_dump_context context);
2685 nobug_resource_state (struct nobug_resource_user* resource,
2686 enum nobug_resource_state state);
2689 void
2690 nobug_resource_list (const struct nobug_resource_dump_context context);
2694 global config, data and defaults
2696 void nobug_init (const struct nobug_context context);
2699 the destroy function is optional, since nobug should stay alive for the whole application lifetime
2700 (and destroying is global!) it is only provided for the nobug testsuite itself
2702 void nobug_destroy (const struct nobug_context context);
2704 void
2705 nobug_backtrace_glibc (const struct nobug_context context);
2707 void
2708 nobug_backtrace_valgrind (const struct nobug_context context);
2710 char*
2711 nobug_log_begin (char* header, struct nobug_flag* flag, const char* what, const struct nobug_context ctx);
2714 void
2715 nobug_log_end (struct nobug_flag* flag, int lvl);
2718 /* must be called inbetween log_begin and log_end */
2719 void
2720 nobug_log_line (char** start, char* header, struct nobug_flag* flag, int lvl, const char* fmt, ...);
2723 void
2724 nobug_log (struct nobug_flag* flag, int lvl, const char* what,
2725 const struct nobug_context ctx,
2726 const char* fmt, ...) NOBUG_ATTR_PRINTF(5, 6);
2729 extern struct nobug_ringbuffer nobug_default_ringbuffer;
2730 extern FILE* nobug_default_file;
2731 extern struct nobug_flag nobug_flag_NOBUG_ON;
2732 extern struct nobug_flag nobug_flag_NOBUG_ANN;
2733 extern struct nobug_flag nobug_flag_nobug;
2734 extern unsigned long long nobug_counter;
2736 //callbacks HEAD- Callbacks; callbacks; function hooks to catch nobug actions
2737 //callbacks
2738 //callbacks NoBug provides callbacks, applications can use these
2739 //callbacks to present logging information in some custom way or hook some special processing in.
2740 //callbacks The callbacks are initialized to NULL and never modified by NoBug, its the solve responsibility
2741 //callbacks of the user to manage them.
2742 //callbacks
2743 //callbacks CAUTION: There are certain constraints what and what not can be done in callbacks
2744 //callbacks documented below which must be followed.
2745 //callbacks
2746 //callbacks PARA logging callback functiontype; logging_cb; type of a logging callback function
2747 //callbacks
2748 typedef void (*nobug_logging_cb)(const struct nobug_flag* flag, //callbacks VERBATIM;
2749 int priority, //callbacks VERBATIM;
2750 const char *log, //callbacks VERBATIM;
2751 void* data); //callbacks VERBATIM;
2752 //callbacks
2753 //callbacks `flag`::
2754 //callbacks Flag structure which defines the logging configuration for this event
2755 //callbacks `priority`::
2756 //callbacks Log level of the current event
2757 //callbacks `log`::
2758 //callbacks Pointing to the current log line in the ringbuffer or `NULL`
2759 //callbacks `data`::
2760 //callbacks Global pointer defined by the user, passed arround (see below)
2761 //callbacks
2763 //callbacks PARA abort callback functiontype; abort_cb; type of a abort callback function
2764 //callbacks
2765 typedef void (*nobug_abort_cb)(void* data); //callbacks VERBATIM;
2766 //callbacks
2767 //callbacks `data`::
2768 //callbacks Global data defined by the user, passed arround (see below)
2769 //callbacks
2771 //callbacks PARA passing data to callbacks; callback_data; data to be passed to callbacks
2772 //callbacks
2773 extern
2774 void* nobug_callback_data; //callbacks VERBATIM;
2775 //callbacks
2776 //callbacks This global variable is initialized to `NULL` and will never be touched by NoBug. One can use it
2777 //callbacks to pass extra data to the callback functions.
2778 //callbacks
2780 //callbacks PARA callback when logging; logging_callback; hook when something get logged
2781 //callbacks
2782 extern
2783 nobug_logging_cb nobug_logging_callback; //callbacks VERBATIM;
2784 //callbacks
2785 //callbacks This callback gets called when something gets logged.
2786 //callbacks NoBug will still hold its mutexes when calling this hook, calling NoBug logging or resource tracking
2787 //callbacks functions from here recursively will deadlock and must be avoided.
2788 //callbacks The `log` parameter points to the logging message in the ringbuffer.
2789 //callbacks Unlike other logging targets it is not automatically limited to the log level configured
2790 //callbacks in the flag but called unconditionally. The callback should implement its own limiting.
2791 //callbacks
2792 //callbacks When one wants to do complex calls which may include recursion into logging and resource tracking
2793 //callbacks functions, the intended way is to pass contextual information possibly including a __copy__ of the
2794 //callbacks `log` parameter in xref:THREAD_DATA[NOBUG_THREAD_DATA] to the postlogging callback (see below).
2795 //callbacks Other internal NoBug facilties, like the ringbuffer etc, are protected by the mutexes and may be accessed
2796 //callbacks from this function.
2797 //callbacks
2799 //callbacks PARA callback after logging; postlogging_callback; hook after something get logged
2800 //callbacks
2801 extern
2802 nobug_logging_cb nobug_postlogging_callback; //callbacks VERBATIM;
2803 //callbacks
2804 //callbacks This callback gets called after something got logged. The `log` parameter is always NULL and all
2805 //callbacks NoBug mutexes are released. This means that this function may call any complex things, including
2806 //callbacks calling logging and resource tracking, but may not call internal NoBug facilities.
2807 //callbacks Contextual created in the `nobug_logging_callback` and stored in xref:THREAD_DATA[NOBUG_THREAD_DATA] can be
2808 //callbacks retrieved here and may need to be cleaned up here.
2809 //callbacks
2811 //callbacks PARA callback for aborting; abort_callback; hook to handle a termination
2812 //callbacks
2813 extern
2814 nobug_abort_cb nobug_abort_callback; //callbacks VERBATIM;
2815 //callbacks
2816 //callbacks This callback gets called when the application shall be terminated due an error.
2817 //callbacks It can be used to hook exceptions or similar things in. When it returns, `abort()`
2818 //callbacks is called.
2819 //callbacks
2820 //callbacks IMPORTANT: Errors detected by NoBug are always fatal. If one handles and possible
2821 //callbacks throws an exception here, the application must shut down as soon as possible.
2822 //callbacks Most causes for aborts are optimitzed out in `RELEASE` builds.
2823 //callbacks
2826 /* block statement macros for sections must not be left by a jump this function will assert this with a NOBUG_CLEANUP attribute */
2827 static inline void
2828 nobug_section_cleaned (int* self)
2830 if (!self)
2832 nobug_log (&nobug_flag_NOBUG_ON,
2833 LOG_EMERG, "RESOURCE_SECTION",
2834 NOBUG_CONTEXT_NIL,
2835 "illegal leaving of resource section (goto, return, ..)");
2836 abort();
2842 fault coverage checking
2845 struct nobug_coverage_record
2847 uint64_t hash;
2848 char state; /* 'F' from FAILURE or 'P' from PASS */
2851 extern void* nobug_coverage_tree;
2853 void
2854 nobug_coverage_parse_log (FILE* log);
2856 struct nobug_coverage_record
2857 nobug_coverage_check (void);
2859 void
2860 nobug_coverage_init (const struct nobug_context context);
2864 #ifdef __cplusplus
2865 } /* extern "C" */
2866 #endif
2868 #ifndef NOBUG_LIBNOBUG_C
2871 tag this translation unit as unchecked in ALPHA and BETA builds
2873 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED;)
2875 #else
2876 /* some configuration when compiling nobug */
2877 /* Maximal length of a log line header (silently truncated if exceed) */
2878 #define NOBUG_MAX_LOG_HEADER_SIZE 128
2879 /* Maximal linebreaks in a single logging instruction which get translated to multiple lines */
2880 #define NOBUG_MAX_LOG_LINES 32
2882 #endif /* NOBUG_LIBNOBUG_C */
2883 #endif