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