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