Preparation for the upcoming deadlock detector
[nobug.git] / src / nobug.h
blob10e953e49bf83dacbf5534c174a73fda929740e6
1 /*
2 This file is part of the NoBug debugging library.
4 Copyright (C)
5 2007, 2008, 2009 Christian Thaeter <ct@pipapo.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
20 #ifndef NOBUG_H
21 #define NOBUG_H
23 #ifndef NOBUG_LIBNOBUG_C /* not when building libnobug */
24 #ifdef NDEBUG
25 #ifdef EBUG_ALPHA
26 #error NDEBUG incompatible with -DEBUG_ALPHA
27 #endif
28 #ifdef EBUG_BETA
29 #error NDEBUG incompatible with -DEBUG_BETA
30 #endif
31 #endif
33 #if defined(EBUG_ALPHA)
34 # define NOBUG_MODE_ALPHA 1
35 # define NOBUG_MODE_BETA 0
36 # define NOBUG_MODE_RELEASE 0
37 #elif defined(EBUG_BETA)
38 # define NOBUG_MODE_ALPHA 0
39 # define NOBUG_MODE_BETA 1
40 # define NOBUG_MODE_RELEASE 0
41 #elif defined(NDEBUG)
42 # define NOBUG_MODE_ALPHA 0
43 # define NOBUG_MODE_BETA 0
44 # define NOBUG_MODE_RELEASE 1
45 #else
46 #error no debug level and no NDEBUG defined
47 #endif
48 #endif /* NOBUG_LIBNOBUG_C */
51 HEADERS
54 #include <syslog.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <stdio.h>
58 #include <stdarg.h>
60 #ifdef HAVE_EXECINFO_H
61 # ifndef NOBUG_USE_EXECINFO
62 # define NOBUG_USE_EXECINFO 1
63 # endif
64 #else
65 # undef NOBUG_USE_EXECINFO
66 # define NOBUG_USE_EXECINFO 0
67 #endif
69 #if NOBUG_USE_EXECINFO
70 #include <execinfo.h>
71 #endif
73 #if defined(HAVE_VALGRIND) && !defined(NVALGRIND)
74 # ifndef NOBUG_USE_VALGRIND
75 # define NOBUG_USE_VALGRIND 1
76 # endif
77 #else
78 # undef NOBUG_USE_VALGRIND
79 # define NOBUG_USE_VALGRIND 0
80 #endif
82 #if NOBUG_USE_VALGRIND
83 #include <valgrind.h>
84 #endif
86 #ifdef HAVE_PTHREAD
87 # ifndef NOBUG_USE_PTHREAD
88 # define NOBUG_USE_PTHREAD 1
89 # endif
90 #else
91 # ifdef NOBUG_USE_PTHREAD
92 # undef NOBUG_USE_PTHREAD
93 # endif
94 # define NOBUG_USE_PTHREAD 0
95 #endif
97 #if NOBUG_USE_PTHREAD
98 #include <pthread.h>
99 #endif
101 #if NOBUG_MODE_RELEASE==0
103 //index.assert xref:assert[assert]:: C standard assertion
104 //assertions [[assert]]
105 //assertions .assert
106 //assertions assert(expr)
107 //assertions
108 //assertions NoBug overrides the standard assert macro in *ALPHA* and *BETA* builds.
109 //assertions This is just a compatibility feature, its use is not suggested.
110 //assertions
112 #undef assert
113 #define assert(expr) NOBUG_ASSERT(expr)
114 #endif
118 ASSERTIONS
122 //index.require xref:REQUIRE[REQUIRE]:: preconditions (incoming parameters)
123 //assertions [[REQUIRE]]
124 //assertions .REQUIRE
125 //assertions REQUIRE(expr, ...)
126 //assertions REQUIRE_DBG(expr, ...)
127 //assertions REQUIRE_IF(when, expr, ...)
128 //assertions REQUIRE_IF_DBG(when, expr, ...)
129 //assertions
130 //assertions Precondition (input) check. Use these macros to validate input a
131 //assertions function receives. The checks are enabled in *ALPHA* and *BETA* builds and
132 //assertions optimized out in *RELEASE* builds.
133 //assertions
135 #define NOBUG_REQUIRE(expr, ...) \
136 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", \
137 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
140 #define NOBUG_REQUIRE_DBG(expr, ...) \
141 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_DBG_(expr, "PRECONDITION", \
142 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
145 #define NOBUG_REQUIRE_IF(when, expr, ...) \
146 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_REQUIRE(expr, ## __VA_ARGS__)))
148 #define NOBUG_REQUIRE_IF_DBG(when, expr, ...) \
149 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_REQUIRE_DBG(expr, ## __VA_ARGS__)))
153 //index.ensure xref:ENSURE[ENSURE]:: postconditions (computation outcomes)
154 //assertions [[ENSURE]]
155 //assertions .ENSURE
156 //assertions ENSURE(expr, ...)
157 //assertions ENSURE_DBG(expr, ...)
158 //assertions ENSURE_IF(when, expr, ...)
159 //assertions ENSURE_IF_DBG(when, expr, ...)
160 //assertions
161 //assertions Postcondition (progress/output) check. Use these macros to validate the
162 //assertions data a function produces (example: return value). The checks enabled
163 //assertions unconditionally in *ALPHA* builds and optimized out in *BETA* builds for
164 //assertions scopes which are tagged as `CHECKED`. In *RELEASE* builds this checks are
165 //assertions always optimized out, but scopes tagged as `UNCHECKED` are not permitted.
166 //assertions
168 #define NOBUG_ENSURE(expr, ...) \
169 NOBUG_IF_ALPHA (NOBUG_ASSERT_(expr, "POSTCONDITION", \
170 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
171 NOBUG_IF_BETA ( \
172 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
173 NOBUG_ASSERT_(expr, "POSTCONDITION", \
174 NOBUG_LOCATION_INFO, ## __VA_ARGS__))\
177 #define NOBUG_ENSURE_DBG(expr, ...) \
178 NOBUG_IF_ALPHA (NOBUG_ASSERT_DBG_ (expr, "POSTCONDITION", \
179 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
180 NOBUG_IF_BETA ( \
181 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
182 NOBUG_ASSERT_DBG_(expr, "POSTCONDITION", \
183 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
187 #define NOBUG_ENSURE_IF(when, expr, ...) \
188 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE(expr, ## __VA_ARGS__)))
190 #define NOBUG_ENSURE_IF_DBG(when, expr, ...) \
191 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE_DBG(expr, ## __VA_ARGS__)))
195 generic assertion
197 //index.assert xref:ASSERT[ASSERT]:: generic assertion
198 //assertions [[ASSERT]]
199 //assertions .ASSERT
200 //assertions ASSERT(expr, ...)
201 //assertions ASSERT_DBG(expr, ...)
202 //assertions ASSERT_IF(when, expr, ...)
203 //assertions ASSERT_IF_DBG(when, expr, ...)
204 //assertions
205 //assertions Generic check. Use these macros when you want to validate something
206 //assertions which doesn't fall into one of the above categories. A example is when
207 //assertions a library function can return a unexpected result (scanf with syntax
208 //assertions error in the formatstring, when a constant/literal formatstring is
209 //assertions expected). The checks are enabled in *ALPHA* and *BETA* builds and
210 //assertions optimized out in *RELEASE* builds.
211 //assertions
213 #define NOBUG_ASSERT(expr, ...) \
214 NOBUG_IF_NOT_RELEASE( \
215 NOBUG_ASSERT_(expr, "ASSERTION", \
216 NOBUG_LOCATION_INFO, ## __VA_ARGS__) \
219 #define NOBUG_ASSERT_DBG(expr, ...) \
220 NOBUG_IF_NOT_RELEASE( \
221 NOBUG_ASSERT_DBG_(expr, "ASSERTION", \
222 NOBUG_LOCATION_INFO, ## __VA_ARGS__) \
225 #define NOBUG_ASSERT_IF(when, expr, ...) \
226 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT(expr, ## __VA_ARGS__)))
228 #define NOBUG_ASSERT_IF_DBG(when, expr, ...) \
229 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT_DBG(expr, ## __VA_ARGS__)))
234 //index.check xref:CHECK[CHECK]:: assertion for testsuites
235 //assertions [[CHECK]]
236 //assertions .CHECK
237 //assertions CHECK(expr, ...)
238 //assertions CHECK_IF(when, expr, ...)
239 //assertions
240 //assertions This assertion is never optimized out. Its main purpose is for implementing
241 //assertions testsuites where one want to assert tests independent of the build level
242 //assertions
244 #define NOBUG_CHECK(expr, ...) \
245 NOBUG_ASSERT_(expr, "CHECK", NOBUG_LOCATION_INFO, ## __VA_ARGS__)
247 #define NOBUG_CHECK_IF(when, expr, ...) \
248 NOBUG_WHEN(when, NOBUG_CHECK(expr, ## __VA_ARGS__))
253 low level assert
255 #define NOBUG_ASSERT_(expr, what, location, ...) \
256 NOBUG_WHEN (!(expr), \
257 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
258 location, what, "(%s) " \
259 NOBUG_HEAD(__VA_ARGS__), \
260 #expr NOBUG_TAIL(__VA_ARGS__)); \
261 NOBUG_BACKTRACE; \
262 NOBUG_ABORT \
265 #define NOBUG_ASSERT_DBG_(expr, what, location, ...) \
266 NOBUG_WHEN (NOBUG_ACTIVE_DBG && !(expr), \
267 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
268 location, what, "(%s) " \
269 NOBUG_HEAD(__VA_ARGS__), \
270 #expr NOBUG_TAIL(__VA_ARGS__)); \
271 NOBUG_BACKTRACE; \
272 NOBUG_ABORT \
277 //index.invariant xref:INVARIANT[INVARIANT]:: validate the state
278 //assertions [[INVARIANT]]
279 //assertions .INVARIANT
280 //assertions INVARIANT(type, pointer, depth)
281 //assertions INVARIANT_DBG(type, pointer, depth)
282 //assertions INVARIANT_IF(when,type, pointer, depth)
283 //assertions INVARIANT_IF_DBG(when, type, pointer, depth)
284 //assertions
285 //assertions Checking invariants. You can provide more complex checking functions
286 //assertions which test the validity of datastructures. Invariants are only enabled
287 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
288 //assertions otherwise optimized out.
289 //assertions
290 //assertions TODO: describe how to create invariant checks
291 //assertions
293 #define NOBUG_INVARIANT(type, pointer, depth) \
294 NOBUG_IF_ALPHA( \
295 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
296 NOBUG_CAT(type,_invariant)(pointer, depth, \
297 NOBUG_LOCATION_ARGS) \
301 #define NOBUG_INVARIANT_DBG(type, pointer, ...) \
302 NOBUG_IF_ALPHA( \
303 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED && NOBUG_ACTIVE_DBG, \
304 NOBUG_CAT(type,_invariant)(pointer, depth, \
305 NOBUG_LOCATION_ARGS) \
309 #define NOBUG_INVARIANT_IF(when, type, pointer, ...) \
310 NOBUG_IF_ALPHA (NOBUG_WHEN (when, \
311 NOBUG_INVARIANT(type, pointer, ## __VA_ARGS__)) \
314 #define NOBUG_INVARIANT_IF_DBG(when, type, pointer, ...) \
315 NOBUG_IF_ALPHA (NOBUG_WHEN (when, \
316 NOBUG_INVARIANT_DBG(type, pointer, ## __VA_ARGS__))\
319 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
320 NOBUG_ASSERT_(expr, "INVARIANT", (file, line, func), ## __VA_ARGS__)
324 checked/unchecked tagged scopes
326 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
328 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
330 #define NOBUG_UNCHECKED \
331 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
332 NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
337 dumping datastructures
339 /*TODO dump-level for flags instead limits[0]*/
341 //index.dump xref:DUMP[DUMP]:: dumping datastructures
342 //dumpmacros [[DUMP]]
343 //dumpmacros * DUMP(flag, type, pointer, depth)
344 //dumpmacros + Dump a datastructure
345 //dumpmacros DUMP_IF(expr, flag, type, pointer, depth)
346 //dumpmacros + Dump datastructure if expr is true
347 //dumpmacros
348 //dumpmacros This macros call a datastructure dump of the object (`pointer`) in question.
349 //dumpmacros `DUMP_IF` is the only enabled dumping macro for the RELEASE build level.
350 //dumpmacros
352 #define NOBUG_DUMP(flag, type, pointer, depth) \
353 NOBUG_IF_NOT_RELEASE( \
354 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
355 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
356 NOBUG_LOCATION_ARGS) \
360 #define NOBUG_DUMP_DBG(flag, type, pointer, depth) \
361 NOBUG_IF_NOT_RELEASE( \
362 NOBUG_WHEN (NOBUG_ACTIVE_DBG && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
363 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
364 NOBUG_LOCATION_ARGS) \
368 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth) \
369 NOBUG_WHEN (when && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
370 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
371 NOBUG_LOCATION_ARGS) \
374 #define NOBUG_DUMP_IF_DBG(when, flag, type, pointer, depth) \
375 NOBUG_IF_NOT_RELEASE( \
376 NOBUG_WHEN (NOBUG_ACTIVE_DBG && when && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET],\
377 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
378 NOBUG_LOCATION_ARGS) \
384 //index.dump_log xref:DUMP_LOG[DUMP_LOG]:: Logging functions for dumping
385 //dumpmacros [[DUMP_LOG]]
386 //dumpmacros .DUMP_LOG
387 //dumpmacros DUMP_LOG(fmt, ...)
388 //dumpmacros DUMP_LOG_DBG(fmt, ...)
389 //dumpmacros DUMP_LOG_IF(when, fmt, ...)
390 //dumpmacros DUMP_LOG_IF_DBG(when, fmt, ...)
391 //dumpmacros
392 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
393 //dumpmacros
394 //dumpmacros Dumping is by default done on level `LOG_DEBUG`, this can be overridden by
395 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other level.
396 //dumpmacros
398 #define NOBUG_DUMP_LOG(fmt, ...) \
399 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
400 (file, line, func), "DUMP", \
401 fmt, ## __VA_ARGS__)
404 #define NOBUG_DUMP_LOG_DBG(fmt, ...) \
405 NOBUG_WHEN (NOBUG_ACTIVE_DBG, \
406 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
407 (file, line, func), "DUMP", \
408 fmt, ## __VA_ARGS__) \
411 #define NOBUG_DUMP_LOG_IF(expr, fmt, ...) \
412 NOBUG_WHEN (expr, \
413 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
414 (file, line, func), "DUMP", \
415 fmt, ## __VA_ARGS__) \
418 #define NOBUG_DUMP_LOG_IF_DBG(expr, fmt, ...) \
419 NOBUG_WHEN (NOBUG_ACTIVE_DBG && expr, \
420 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
421 (file, line, func), "DUMP", \
422 fmt, ## __VA_ARGS__) \
426 #ifndef NOBUG_DUMP_LEVEL
427 #define NOBUG_DUMP_LEVEL LOG_DEBUG
428 #endif
431 Logging
435 //index.echo xref:ECHO[ECHO]:: logging for tests
436 //logmacros [[ECHO]]
437 //logmacros .ECHO
438 //logmacros ECHO(...)
439 //logmacros
440 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
441 //logmacros testsuites where one want to print and log messages independent of the build level
442 //logmacros
444 #define NOBUG_ECHO(...) \
445 NOBUG_LOG_(&nobug_flag_NOBUG_ON, LOG_NOTICE, NOBUG_LOCATION_INFO, "ECHO", ## __VA_ARGS__)
448 //index.alert xref:ALERT[ALERT]:: about to die
449 //logmacros [[ALERT]]
450 //logmacros .ALERT
451 //logmacros ALERT(flag, ...)
452 //logmacros ALERT_DBG(flag, ...)
453 //logmacros ALERT_IF(when, flag, ...)
454 //logmacros ALERT_IF_DBG(when, flag, ...)
455 //logmacros
456 //logmacros This is the most critical condition an application might log. This might be used
457 //logmacros if an error occurs which can not be handled except a safe shutdown for example.
458 //logmacros
460 #define NOBUG_ALERT(flag, ...) \
461 NOBUG_LOG(flag, LOG_ALERT, ## __VA_ARGS__)
462 #define NOBUG_ALERT_IF(expr, flag, ...) \
463 NOBUG_LOG_IF(expr, flag, LOG_ALERT, ## __VA_ARGS__)
464 #define NOBUG_ALERT_DBG(flag, ...) \
465 NOBUG_LOG_DBG(flag, LOG_ALERT, ## __VA_ARGS__)
466 #define NOBUG_ALERT_IF_DBG(expr, flag, ...) \
467 NOBUG_LOG_IF_DBG(expr, flag, LOG_ALERT, ## __VA_ARGS__)
470 //index.critical xref:CRITICAL[CRITICAL]:: can not continue
471 //logmacros [[CRITICAL]]
472 //logmacros .CRITICAL
473 //logmacros CRITICAL(flag, ...)
474 //logmacros CRITICAL_DBG(flag, ...)
475 //logmacros CRITICAL_IF(when, flag, ...)
476 //logmacros CRITICAL_IF_DBG(when, flag, ...)
477 //logmacros
478 //logmacros An error which can not be handled occured but the application does not need to be
479 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
480 //logmacros
482 #define NOBUG_CRITICAL(flag, ...) \
483 NOBUG_LOG(flag, LOG_CRIT, ## __VA_ARGS__)
484 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
485 NOBUG_LOG_IF(expr, flag, LOG_CRIT, ## __VA_ARGS__)
486 #define NOBUG_CRITICAL_DBG(flag, ...) \
487 NOBUG_LOG_DBG(flag, LOG_CRIT, ## __VA_ARGS__)
488 #define NOBUG_CRITICAL_IF_DBG(expr, flag, ...) \
489 NOBUG_LOG_IF_DBG(expr, flag, LOG_CRIT, ## __VA_ARGS__)
492 //index.error xref:ERROR[ERROR]:: something gone wrong
493 //logmacros [[ERROR]]
494 //logmacros .ERROR
495 //logmacros ERROR(flag, fmt, ...)
496 //logmacros ERROR_DBG(flag, fmt, ...)
497 //logmacros ERROR_IF(when, flag, fmt, ...)
498 //logmacros ERROR_IF_DBG(when, flag, fmt, ...)
499 //logmacros
500 //logmacros Application takes a error handling brach
501 //logmacros
503 #define NOBUG_ERROR(flag, ...) \
504 NOBUG_LOG(flag, LOG_ERR, ## __VA_ARGS__)
505 #define NOBUG_ERROR_IF(expr, flag, ...) \
506 NOBUG_LOG_IF(expr, flag, LOG_ERR, ## __VA_ARGS__)
507 #define NOBUG_ERROR_DBG(flag, ...) \
508 NOBUG_LOG_DBG(flag, LOG_ERR, ## __VA_ARGS__)
509 #define NOBUG_ERROR_IF_DBG(expr, flag, ...) \
510 NOBUG_LOG_IF_DBG(expr, flag, LOG_ERR, ## __VA_ARGS__)
513 //index.warn xref:WARN[WARN]:: unexpected fixable error
514 //logmacros [[WARN]]
515 //logmacros .WARN
516 //logmacros WARN(flag, fmt, ...)
517 //logmacros WARN_DBG(flag, fmt, ...)
518 //logmacros WARN_IF(when, flag, fmt, ...)
519 //logmacros WARN_IF_DBG(when, flag, fmt, ...)
520 //logmacros
521 //logmacros Rare, handled but unexpected branch
522 //logmacros
524 #define NOBUG_WARN(flag, ...) \
525 NOBUG_LOG(flag, LOG_WARNING, ## __VA_ARGS__)
526 #define NOBUG_WARN_IF(expr, flag, ...) \
527 NOBUG_LOG_IF(expr, flag, LOG_WARNING, ## __VA_ARGS__)
528 #define NOBUG_WARN_DBG(flag, ...) \
529 NOBUG_LOG_DBG(flag, LOG_WARNING, ## __VA_ARGS__)
530 #define NOBUG_WARN_IF_DBG(expr, flag, ...) \
531 NOBUG_LOG_IF_DBG(expr, flag, LOG_WARNING, ## __VA_ARGS__)
534 //index.info xref:INFO[INFO]:: progress message
535 //logmacros [[INFO]]
536 //logmacros .INFO
537 //logmacros INFO(flag, fmt, ...)
538 //logmacros INFO_DBG(flag, fmt, ...)
539 //logmacros INFO_IF(when, flag, fmt, ...)
540 //logmacros INFO_IF_DBG(when, flag, fmt, ...)
541 //logmacros
542 //logmacros Message about program progress
543 //logmacros
545 #define NOBUG_INFO(flag, ...) \
546 NOBUG_LOG(flag, LOG_INFO, ## __VA_ARGS__)
547 #define NOBUG_INFO_IF(expr, flag, ...) \
548 NOBUG_LOG_IF(expr, flag, LOG_INFO, ## __VA_ARGS__)
549 #define NOBUG_INFO_DBG(flag, ...) \
550 NOBUG_LOG_DBG(flag, LOG_INFO, ## __VA_ARGS__)
551 #define NOBUG_INFO_IF_DBG(expr, flag, ...) \
552 NOBUG_LOG_IF_DBG(expr, flag, LOG_INFO, ## __VA_ARGS__)
555 //index.notice xref:NOTICE[NOTICE]:: detailed progress message
556 //logmacros [[NOTICE]]
557 //logmacros .NOTICE
558 //logmacros NOTICE(flag, fmt, ...)
559 //logmacros NOTICE_DBG(flag, fmt, ...)
560 //logmacros NOTICE_IF(when, flag, fmt, ...)
561 //logmacros NOTICE_IF_DBG(when, flag, fmt, ...)
562 //logmacros
563 //logmacros More detailed progress message
564 //logmacros
566 #define NOBUG_NOTICE(flag, ...) \
567 NOBUG_LOG(flag, LOG_NOTICE, ## __VA_ARGS__)
568 #define NOBUG_NOTICE_IF(expr, flag, ...) \
569 NOBUG_LOG_IF(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
570 #define NOBUG_NOTICE_DBG(flag, ...) \
571 NOBUG_LOG_DBG(flag, LOG_NOTICE, ## __VA_ARGS__)
572 #define NOBUG_NOTICE_IF_DBG(expr, flag, ...) \
573 NOBUG_LOG_IF_DBG(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
576 //index.trace xref:TRACE[TRACE]:: debugging level message
577 //logmacros [[TRACE]]
578 //logmacros .TRACE
579 //logmacros TRACE(flag, fmt, ...)
580 //logmacros TRACE_DBG(flag, fmt, ...)
581 //logmacros TRACE_IF(when, flag, fmt, ...)
582 //logmacros TRACEIF_DBG(when, flag, fmt, ...)
583 //logmacros
584 //logmacros Very fine grained messages
585 //logmacros
586 //logmacros NOTE: that `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
587 //logmacros
589 #define NOBUG_TRACE(flag, ...) \
590 NOBUG_LOG(flag, LOG_DEBUG, ## __VA_ARGS__)
591 #define NOBUG_TRACE_IF(expr, flag, ...) \
592 NOBUG_LOG_IF(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
593 #define NOBUG_TRACE_DBG(flag, ...) \
594 NOBUG_LOG_DBG(flag, LOG_DEBUG, ## __VA_ARGS__)
595 #define NOBUG_TRACE_IF_DBG(expr, flag, ...) \
596 NOBUG_LOG_IF_DBG(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
600 //index.log xref:LOG[LOG]:: generic logging
601 //logmacros [[LOG]]
602 //logmacros .LOG
603 //logmacros LOG(flag, lvl, fmt, ...)
604 //logmacros LOG_DBG(flag, lvl, fmt, ...)
605 //logmacros LOG_IF(when, flag, lvl, fmt, ...)
606 //logmacros LOG_IF_DBG(when, flag, lvl, fmt, ...)
607 //logmacros
608 //logmacros Generic logging macro which takes the level explicitly,
609 //logmacros avoid this, unless you implement your own logging facilities.
610 //logmacros
612 #define NOBUG_LOG(flag, lvl, ...) \
613 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
614 NOBUG_LVL(lvl), ## __VA_ARGS__)
616 #define NOBUG_LOG_DBG(flag, lvl, ...) \
617 NOBUG_WHEN (NOBUG_ACTIVE_DBG, \
618 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
619 NOBUG_LVL(lvl), ## __VA_ARGS__) \
622 #define NOBUG_LOG_IF(expr, flag, lvl, ...) \
623 NOBUG_WHEN (expr, \
624 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
625 NOBUG_LVL(lvl), ## __VA_ARGS__) \
628 #define NOBUG_LOG_IF_DBG(expr, flag, lvl, ...) \
629 NOBUG_WHEN (NOBUG_ACTIVE_DBG && expr, \
630 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
631 NOBUG_LVL(lvl), ## __VA_ARGS__) \
636 low level logging handler
638 #define NOBUG_LOG_(flag, lvl, location, what, ...) \
639 NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER], \
640 nobug_log (flag, lvl, \
641 "%0.10llu: %s: %s:%d:"NOBUG_THREAD_ID_FMT(" ",":")" %s: " \
642 NOBUG_HEAD(__VA_ARGS__), ++nobug_counter, what, \
643 NOBUG_LOCATION_FILE location, \
644 NOBUG_LOCATION_LINE location NOBUG_THREAD_ID_COMMA, \
645 NOBUG_LOCATION_FUNC location NOBUG_TAIL(__VA_ARGS__)) \
648 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
649 #define NOBUG_LVL_0 "EMERG"
650 #define NOBUG_LVL_1 "ALERT"
651 #define NOBUG_LVL_2 "CRIT"
652 #define NOBUG_LVL_3 "ERR"
653 #define NOBUG_LVL_4 "WARNING"
654 #define NOBUG_LVL_5 "NOTICE"
655 #define NOBUG_LVL_6 "INFO"
656 #define NOBUG_LVL_7 "TRACE"
659 //index.log_baselimit xref:LOG_BASELIMIT[LOG_BASELIMIT]:: minimum compliled-in logging limit
660 //logmacros [[LOG_BASELIMIT]]
661 //logmacros .LOG_BASELIMIT
662 //logmacros NOBUG_LOG_BASELIMIT_ALPHA
663 //logmacros NOBUG_LOG_BASELIMIT_BETA
664 //logmacros NOBUG_LOG_BASELIMIT_RELEASE
665 //logmacros NOBUG_LOG_BASELIMIT
666 //logmacros
667 //logmacros NoBug defines some logging base limits, anything more detailed
668 //logmacros than this base limits will be optimized out. This is used to
669 //logmacros reduce the logging overhead for *RELEASE* builds.
670 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
671 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
672 //logmacros builds to log the application progress only coarsely then.
673 //logmacros
674 //logmacros This macros can be defined before including 'nobug.h' to some other
675 //logmacros log level (as defined in 'syslog.h').
676 //logmacros
678 #ifndef NOBUG_LOG_BASELIMIT_ALPHA
679 #define NOBUG_LOG_BASELIMIT_ALPHA LOG_DEBUG
680 #endif
682 #ifndef NOBUG_LOG_BASELIMIT_BETA
683 #define NOBUG_LOG_BASELIMIT_BETA LOG_DEBUG
684 #endif
686 #ifndef NOBUG_LOG_BASELIMIT_RELEASE
687 #define NOBUG_LOG_BASELIMIT_RELEASE LOG_NOTICE
688 #endif
690 #ifndef NOBUG_LOG_BASELIMIT
691 #define NOBUG_LOG_BASELIMIT \
692 NOBUG_IF_ALPHA(NOBUG_LOG_BASELIMIT_ALPHA) \
693 NOBUG_IF_BETA(NOBUG_LOG_BASELIMIT_BETA) \
694 NOBUG_IF_RELEASE(NOBUG_LOG_BASELIMIT_RELEASE)
695 #endif
698 Annotations
702 alpha beta release
703 DEPRECATED log nothing wont compile
705 //index.deprecated xref:DEPRECATED[DEPRECATED]:: to be discarded in future
706 //annotations [[DEPRECATED]]
707 //annotations * DEPRECATED(...)
708 //annotations + Something which shouldn't be used in future
709 //annotations
711 #define NOBUG_DEPRECATED(msg) \
712 NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN, \
713 NOBUG_LOCATION_INFO, "DEPRECATED", msg) \
715 NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
719 alpha beta release
720 UNIMPLEMENTED abort abort wont compile
722 //index.unimplemented xref:UNIMPLEMENTED[UNIMPLEMENTED]:: not yet implemented
723 //annotations [[UNIMPLEMENTED]]
724 //annotations * UNIMPLEMENTED(...)
725 //annotations + not yet finished feature
726 //annotations
728 #define NOBUG_UNIMPLEMENTED(msg) \
729 NOBUG_IF_NOT_RELEASE ( do { \
730 NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG, NOBUG_LOCATION_INFO, \
731 "UNIMPLEMENTED", msg); \
732 NOBUG_ABORT; \
733 } while (0)) \
734 NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
738 alpha beta release
739 FIXME log wont compile wont compile
741 //index.fixme xref:FIXME[FIXME]:: known Bug
742 //annotations [[FIXME]]
743 //annotations * FIXME(...)
744 //annotations + known bug to be fixed later
745 //annotations
747 #define NOBUG_FIXME(msg) \
748 NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT, \
749 NOBUG_LOCATION_INFO, "FIXME", msg))) \
750 NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(msg)) \
751 NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
755 alpha beta release
756 TODO log log wont compile
758 //index.todo xref:TODO[TODO]:: things to be done
759 //annotations [[TODO]]
760 //annotations * TODO(...)
761 //annotations + enhancement to be done soon
762 //annotations
764 #define NOBUG_TODO(msg) \
765 NOBUG_IF_NOT_RELEASE ( \
766 NOBUG_ONCE ( \
767 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE, NOBUG_LOCATION_INFO, \
768 "TODO", msg); \
769 )) \
770 NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
774 alpha beta release
775 PLANNED log nothing nothing
777 //index.planned xref:PLANNED[PLANNED]:: ideas for future
778 //annotations [[PLANNED]]
779 //annotations * PLANNED(...)
780 //annotations + future enhancement
781 //annotations
783 #define NOBUG_PLANNED(msg) \
784 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO, \
785 NOBUG_LOCATION_INFO, "PLANNED", msg)))
789 alpha beta release
790 NOTREACHED abort abort nothing
792 //index.notreached xref:NOTREACHED[NOTREACHED]:: code path never taken
793 //annotations [[NOTREACHED]]
794 //annotations * NOTREACHED
795 //annotations + used to tag code-path which shall be never executed (defaults in switch
796 //annotations statements, `else NOTREACHED;` after series of if's, etc.)
797 //annotations
799 #define NOBUG_NOTREACHED \
800 NOBUG_IF_NOT_RELEASE( do { \
801 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
802 NOBUG_LOCATION_INFO, "NOTREACHED"); \
803 NOBUG_ABORT; \
804 } while (0))
808 Fault injection
810 //faultinjection NoBug has some macros which can be used to simulate errorneous behaviour:
811 //faultinjection
812 //index.inject_goodbad xref:INJECT_GOODBAD[INJECT_GOODBAD]:: fault injection expression
813 //faultinjection [[INJECT_GOODBAD]]
814 //faultinjection * INJECT_GOODBAD(expr, good, bad) substitutes to an expression and returns
815 //faultinjection good when expr is false and bad when expr is true. In BETA and RELEASE
816 //faultinjection builds 'good' is always returned.
817 //faultinjection
819 #define NOBUG_INJECT_GOODBAD(expr, good, bad) \
820 NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);}),bad:good) \
821 NOBUG_IF_NOT_ALPHA(good)
825 //index.inject_fault xref:INJECT_FAULT[INJECT_FAULT]:: fault injection statement
826 //faultinjection [[INJECT_FAULT]]
827 //faultinjection * INJECT_FAULT(expr, bad) substitutes to a statement which executes 'bad'
828 //faultinjection when expr is true. Optimitzed out in BETA and RELEASE builds.
829 //faultinjection
831 #define NOBUG_INJECT_FAULT(expr, bad) \
832 NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
836 //faultinjection In both cases, when a fault is injected it will be logged at
837 //faultinjection NOBUG_INJECT_LEVEL (default: LOG_NOTICE). This can be defined
838 //faultinjection before including 'nobug.h' to override it.
839 //faultinjection
841 #define NOBUG_INJECT_LOG(msg) \
842 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
843 NOBUG_LOCATION_INFO, "INJECT_FAULT", \
844 msg)
847 #ifndef NOBUG_INJECT_LEVEL
848 #define NOBUG_INJECT_LEVEL LOG_NOTICE
849 #endif
853 Flag handling
855 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_, name)
858 //predefflags [[NOBUG_FLAG_RAW]]
859 //index.nobug_flag_raw xref:NOBUG_FLAG_RAW[NOBUG_FLAG_RAW]:: pass direct flag pointer
860 //predefflags .NOBUG_FLAG_RAW
861 //predefflags NOBUG_FLAG_RAW(ptr)
862 //predefflags
863 //predefflags Using this macro one can pass a direct pointer to a flag where a name would
864 //predefflags be expected. This is sometimes convinient when flag pointers are passed around
865 //predefflags in management strutures and one wants to tie logging to dynamic targets.
866 //predefflags
867 //predefflags [source,c]
868 //predefflags ----
869 //predefflags NOBUG_DEFINE_FLAG(myflag);
870 //predefflags ...
871 //predefflags struct nobug_flag* ptr = &NOBUG_FLAG(myflag);
872 //predefflags TRACE(NOBUG_FLAG_RAW(ptr), "Passed flag by pointer")
873 //predefflags ----
874 //predefflags
876 #define nobug_flag_NOBUG_FLAG_RAW(name) *name
878 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
881 #define NOBUG_DEFINE_FLAG(name) \
882 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
883 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
884 struct nobug_flag NOBUG_FLAG(name) = \
885 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
886 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
887 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
888 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
889 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
890 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
894 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
895 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
896 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
897 NOBUG_DECLARE_FLAG(parent); \
898 struct nobug_flag NOBUG_FLAG(name) = \
899 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
900 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
901 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
902 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
903 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
904 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
908 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) \
909 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
910 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
911 struct nobug_flag NOBUG_FLAG(name) = \
912 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
913 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
914 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
915 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
916 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
917 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
921 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
922 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
923 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
924 NOBUG_DECLARE_FLAG(parent); \
925 struct nobug_flag NOBUG_FLAG(name) = \
926 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
927 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
928 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
929 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
930 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
931 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
935 #define NOBUG_INIT_FLAG(name) \
936 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT)
939 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
940 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default)
943 #define NOBUG_CPP_DEFINE_FLAG(name) \
944 NOBUG_FLAG_IF_DECLAREONLY( \
945 NOBUG_DECLARE_FLAG(name); \
946 extern int nobug_cppflag_##name \
948 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
949 NOBUG_DEFINE_FLAG(name); \
950 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
954 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
955 NOBUG_FLAG_IF_DECLAREONLY( \
956 NOBUG_DECLARE_FLAG(name); \
957 extern int nobug_cppflag_##name \
959 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
960 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
961 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
965 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
966 NOBUG_FLAG_IF_DECLAREONLY( \
967 NOBUG_DECLARE_FLAG(name); \
968 extern int nobug_cppflag_##name \
970 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
971 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
972 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
976 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
977 NOBUG_FLAG_IF_DECLAREONLY( \
978 NOBUG_DECLARE_FLAG(name); \
979 extern int nobug_cppflag_##name \
981 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
982 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
983 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
987 #ifndef NOBUG_DECLARE_ONLY
988 #define NOBUG_DECLARE_ONLY 0
989 #endif
991 #define NOBUG_FLAG_IF_DECLAREONLY(...) \
992 NOBUG_IF(NOBUG_DECLARE_ONLY, __VA_ARGS__)
994 #define NOBUG_FLAG_IF_NOT_DECLAREONLY(...) \
995 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
997 #ifdef __cplusplus
998 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
999 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
1000 #else
1001 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
1002 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, NOBUG_ERROR_CANT_DEFINE_AUTOINITIALIZED_CPP_FLAGS_IN_C)
1003 #endif
1005 #ifndef NOBUG_LOG_LIMIT_ALPHA
1006 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
1007 #endif
1008 #ifndef NOBUG_LOG_LIMIT_BETA
1009 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
1010 #endif
1011 #ifndef NOBUG_LOG_LIMIT_RELEASE
1012 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
1013 #endif
1015 #ifndef NOBUG_LOG_LIMIT
1016 # define NOBUG_LOG_LIMIT \
1017 NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA) \
1018 NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA) \
1019 NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
1020 #endif
1022 #ifndef NOBUG_LOG_TARGET_ALPHA
1023 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
1024 #endif
1025 #ifndef NOBUG_LOG_TARGET_BETA
1026 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
1027 #endif
1028 #ifndef NOBUG_LOG_TARGET_RELEASE
1029 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
1030 #endif
1032 #ifndef NOBUG_LOG_TARGET
1033 # define NOBUG_LOG_TARGET \
1034 NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA) \
1035 NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA) \
1036 NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
1037 #endif
1039 #define NOBUG_SET_LIMIT(flag, min) \
1040 NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
1044 Resource registry macros
1048 //index.resource_logging xref:RESOURCE_LOGGING[RESOURCE_LOGGING]:: switch resource logging on and off
1049 //index.resource_log_level xref:RESOURCE_LOGGING[RESOURCE_LOG_LEVEL]:: select the log level for resource logging
1050 //resourcemacros [[RESOURCE_LOGGING]]
1051 //resourcemacros
1052 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
1053 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
1054 //resourcemacros `LOG_DEBUG`.
1055 //resourcemacros
1057 #ifndef NOBUG_RESOURCE_LOGGING
1058 #define NOBUG_RESOURCE_LOGGING 1
1059 #endif
1061 #ifndef NOBUG_RESOURCE_LOG_LEVEL
1062 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
1063 #endif
1067 //index.resource_handle xref:RESOURCE_HANDLE[RESOURCE_HANDLE]:: define an resource handle
1068 //resourcemacros [[RESOURCE_HANDLE]]
1069 //resourcemacros Resources are accessed through handles.
1070 //resourcemacros
1071 //resourcemacros .RESOURCE_HANDLE
1072 //resourcemacros RESOURCE_HANDLE(name)
1073 //resourcemacros
1074 //resourcemacros Defines handles to access resources.
1075 //resourcemacros
1076 //resourcemacros `name`::
1077 //resourcemacros identifer to be used for the handle
1078 //resourcemacros
1079 //resourcemacros This macro takes care that the declaration is optimized out in the same manner
1080 //resourcemacros the rest of the resource tracker would be disabled. You can still instantiate
1081 //resourcemacros handles as `struct nobug_resource_header*` in structures which must have a
1082 //resourcemacros constant size unconditional of the build level.
1083 //resourcemacros
1085 #define NOBUG_RESOURCE_HANDLE(handle) \
1086 NOBUG_IF_ALPHA(struct nobug_resource_header* handle)
1088 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1092 //index.resource_announce xref:RESOURCE_ANNOUNCE[RESOURCE_ANNOUNCE]:: publish new resources
1093 //resourcemacros [[RESOURCE_ANNOUNCE]]
1094 //resourcemacros
1095 //resourcemacros .RESOURCE_ANNOUNCE
1096 //resourcemacros RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
1097 //resourcemacros
1098 //resourcemacros Publishes resources.
1099 //resourcemacros
1100 //resourcemacros `flag`::
1101 //resourcemacros the NoBug flag which turns logging on for this macro
1102 //resourcemacros `type`::
1103 //resourcemacros a string which should denote the domain of the resource,
1104 //resourcemacros examples are "file", "mutex", "lock", "database" and so on
1105 //resourcemacros `name`::
1106 //resourcemacros the actual name of a named resource this as string which
1107 //resourcemacros together with type forms a unique identifier of the resource. `type` and
1108 //resourcemacros `name` must be available through the entire lifetime of the resource, using
1109 //resourcemacros literal strings is recommended
1110 //resourcemacros `identifier`::
1111 //resourcemacros a pointer which should be unique for this resource, any
1112 //resourcemacros kind of pointer will suffice, it is only used for identification. In
1113 //resourcemacros multithreaded applications the thread identifier becomes an additional
1114 //resourcemacros identifier
1115 //resourcemacros `handle`::
1116 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to point to
1117 //resourcemacros the newly created resource.
1118 //resourcemacros
1119 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
1120 //resourcemacros announced more than one time.
1121 //resourcemacros
1123 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
1124 NOBUG_RESOURCE_ANNOUNCE_RAW(&NOBUG_FLAG(flag), type, name, ptr, handle)
1126 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
1127 NOBUG_IF_ALPHA( do { \
1128 NOBUG_REQUIRE(!handle, "Announced resource handle not initialized"); \
1129 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1130 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1131 NOBUG_LOCATION_INFO, "RESOURCE_ANNOUNCE", \
1132 "%s: %s@%p", type, name, ptr);) \
1133 NOBUG_RESOURCE_ASSERT(handle = &nobug_resource_announce (type, name, ptr, \
1134 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__)))->hdr, \
1135 "RESOURCE_ASSERT_ANNOUNCE", NOBUG_LOCATION_INFO, \
1136 "%s: %s@%p %s", type, name, ptr, nobug_resource_error); \
1137 } while (0))
1141 //index.resource_forget xref:RESOURCE_FORGET[RESOURCE_FORGET]:: remove resources
1142 //resourcemacros [[RESOURCE_FORGET]]
1143 //resourcemacros
1144 //resourcemacros .RESOURCE_FORGET
1145 //resourcemacros RESOURCE_FORGET(flag, handle)
1146 //resourcemacros
1147 //resourcemacros Removes resources that have become unavailable from the registry.
1148 //resourcemacros
1149 //resourcemacros `flag`::
1150 //resourcemacros the NoBug flag which turns logging on for this macro
1151 //resourcemacros `handle`::
1152 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1153 //resourcemacros
1154 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1155 //resourcemacros error is raised.
1156 //resourcemacros
1158 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1159 NOBUG_RESOURCE_FORGET_RAW(&NOBUG_FLAG(flag), handle)
1161 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1162 NOBUG_IF_ALPHA( do { \
1163 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1164 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1165 "RESOURCE_FORGET", "%s: %s@%p", \
1166 handle?((struct nobug_resource_record*)handle)->type:"", \
1167 handle?handle->name:"", \
1168 handle?((struct nobug_resource_record*)handle)->object_id:NULL);) \
1169 NOBUG_RESOURCE_ASSERT(nobug_resource_forget ((struct nobug_resource_record*)handle), \
1170 "RESOURCE_ASSERT_FORGET", NOBUG_LOCATION_INFO, "%s: %s@%p: %s", \
1171 handle?((struct nobug_resource_record*)handle)->type:"", \
1172 handle?handle->name:"", \
1173 handle?((struct nobug_resource_record*)handle)->object_id:NULL, \
1174 nobug_resource_error); \
1175 handle = NULL; \
1176 } while (0))
1180 //index.resource_enter xref:RESOURCE_ENTER[RESOURCE_ENTER]:: claim a resource
1181 //resourcemacros [[RESOURCE_ENTER]]
1182 //resourcemacros
1183 //resourcemacros .RESOURCE_ENTER
1184 //resourcemacros RESOURCE_ENTER(flag, announced, name, identifier, state, handle)
1185 //resourcemacros
1186 //resourcemacros Attach a resource to code.
1187 //resourcemacros
1188 //resourcemacros `flag`::
1189 //resourcemacros nobug flag which turns logging on for this macro
1190 //resourcemacros `announced`::
1191 //resourcemacros the handle set by `RESOURCE_ANNOUNCE`
1192 //resourcemacros `name`::
1193 //resourcemacros a free-form identifier
1194 //resourcemacros `identifier`::
1195 //resourcemacros some pointer which must be unique for the user of the
1196 //resourcemacros resource (see above)
1197 //resourcemacros `state`::
1198 //resourcemacros the initial state, one of `NOBUG_RESOURCE_WAITING`,
1199 //resourcemacros `NOBUG_RESOURCE_EXCLUSIVE` or `NOBUG_RESOURCE_RECURSIVE`
1200 //resourcemacros `handle`::
1201 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to the
1202 //resourcemacros entering node
1203 //resourcemacros
1205 #define NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle) \
1206 NOBUG_IF_ALPHA( do { \
1207 NOBUG_REQUIRE(resource, "Announced resource handle not initialized"); \
1208 NOBUG_REQUIRE(!handle, "Resource handle already entered"); \
1209 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1210 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, \
1211 NOBUG_LOCATION_INFO, "RESOURCE_ENTER", \
1212 "%s: %s@%p: %s: %s", \
1213 resource?((struct nobug_resource_record*)resource)->type:"", \
1214 resource?resource->name:"", \
1215 resource?((struct nobug_resource_record*)resource)->object_id:NULL, \
1216 user, \
1217 nobug_resource_states[state]);) \
1218 NOBUG_RESOURCE_ASSERT(handle = &nobug_resource_enter ((struct nobug_resource_record*)resource, \
1219 user, state, \
1220 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__)))->hdr, \
1221 "RESOURCE_ASSERT_ENTER", NOBUG_LOCATION_INFO, \
1222 "%s: %s@%p: %s: %s: %s", \
1223 resource?((struct nobug_resource_record*)resource)->type:"", \
1224 resource?resource->name:"", \
1225 resource?((struct nobug_resource_record*)resource)->object_id:NULL, \
1226 user, nobug_resource_states[state], \
1227 nobug_resource_error); \
1228 } while (0))
1232 //index.resource_state xref:RESOURCE_STATE[RESOURCE_STATE]:: change the state of a resource
1233 //resourcemacros [[RESOURCE_STATE]]
1234 //resourcemacros
1235 //resourcemacros .NOBUG_RESOURCE_STATE
1236 //resourcemacros NOBUG_RESOURCE_STATE(flag, entered, state)
1237 //resourcemacros
1238 //resourcemacros Changes resource's state.
1239 //resourcemacros
1240 //resourcemacros `flag`::
1241 //resourcemacros is nobug flag which turns logging on for this macro
1242 //resourcemacros `state`::
1243 //resourcemacros the new state Note that only certain state transitions are
1244 //resourcemacros allowed, see discussion/diagram above
1245 //resourcemacros `entered`::
1246 //resourcemacros the handle set by `RESOURCE_ENTER`
1247 //resourcemacros
1249 #define NOBUG_RESOURCE_STATE(flag, state, entered) \
1250 NOBUG_RESOURCE_STATE_RAW(&NOBUG_FLAG(flag), state, entered)
1252 #define NOBUG_RESOURCE_STATE_RAW(flag, nstate, entered) \
1253 NOBUG_IF_ALPHA( do { \
1254 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1255 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1256 "RESOURCE_STATE", "%s: %s@%p: %s: %s->%s", \
1257 entered?((struct nobug_resource_user*)entered)->resource->type:"", \
1258 entered?((struct nobug_resource_user*)entered)->resource->hdr.name:"", \
1259 entered?((struct nobug_resource_user*)entered)->resource->object_id:"", \
1260 entered?entered->name:"", \
1261 nobug_resource_states[entered?((struct nobug_resource_user*)entered)->state \
1262 :NOBUG_RESOURCE_INVALID], \
1263 nobug_resource_states[nstate]); \
1265 NOBUG_RESOURCE_ASSERT(nobug_resource_state ((struct nobug_resource_user*)entered, nstate), \
1266 "RESOURCE_ASSERT_STATE", NOBUG_LOCATION_INFO, \
1267 "%s: %s@%p: %s: %s->%s: %s", \
1268 entered?((struct nobug_resource_user*)entered)->resource->type:"", \
1269 entered?((struct nobug_resource_user*)entered)->resource->hdr.name:"", \
1270 entered?((struct nobug_resource_user*)entered)->resource->object_id:"", \
1271 entered?entered->name:"", \
1272 nobug_resource_states[entered?((struct nobug_resource_user*)entered)->state \
1273 :NOBUG_RESOURCE_INVALID], \
1274 nobug_resource_states[nstate], \
1275 nobug_resource_error); \
1276 } while (0))
1280 //index.resource_leave xref:RESOURCE_LEAVE[RESOURCE_LEAVE]:: relinquish a claimed resource
1281 //resourcemacros [[RESOURCE_LEAVE]]
1282 //resourcemacros
1283 //resourcemacros .RESOURCE_LEAVE
1284 //resourcemacros RESOURCE_LEAVE(flag, handle)
1285 //resourcemacros
1286 //resourcemacros Disconnect from a resource identified with its handle.
1287 //resourcemacros
1288 //resourcemacros `flag`::
1289 //resourcemacros nobug flag which turns logging on for this macro
1290 //resourcemacros `handle`::
1291 //resourcemacros the handle you got while entering the resource
1292 //resourcemacros
1294 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1295 NOBUG_RESOURCE_LEAVE_RAW(&NOBUG_FLAG(flag), handle)
1297 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1298 NOBUG_IF_ALPHA( do { \
1299 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1300 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1301 "RESOURCE_LEAVE", "%s: %s@%p: %s: %s", \
1302 handle?((struct nobug_resource_user*)handle)->resource->type:"", \
1303 handle?((struct nobug_resource_user*)handle)->resource->hdr.name:"", \
1304 handle?((struct nobug_resource_user*)handle)->resource->object_id:"", \
1305 handle?handle->name:"", \
1306 nobug_resource_states[handle?((struct nobug_resource_user*)handle)->state \
1307 :NOBUG_RESOURCE_INVALID]); \
1309 NOBUG_RESOURCE_ASSERT(nobug_resource_leave ((struct nobug_resource_user*)handle), \
1310 "RESOURCE_ASSERT_LEAVE", NOBUG_LOCATION_INFO, "%s: %s@%p: %s: %s: %s", \
1311 handle?((struct nobug_resource_user*)handle)->resource->type:"", \
1312 handle?((struct nobug_resource_user*)handle)->resource->hdr.name:"", \
1313 handle?((struct nobug_resource_user*)handle)->resource->object_id:"", \
1314 handle?handle->name:"", \
1315 nobug_resource_states[handle?((struct nobug_resource_user*)handle)->state \
1316 :NOBUG_RESOURCE_INVALID], \
1317 nobug_resource_error); \
1318 handle = NULL; \
1319 } while (0))
1323 /* assertion which dumps all resources */
1324 #define NOBUG_RESOURCE_ASSERT(resource, what, location, ...) \
1325 NOBUG_WHEN (!(resource), \
1326 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
1327 location, what, \
1328 ## __VA_ARGS__); \
1329 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1330 {&nobug_flag_NOBUG_ON, \
1331 LOG_EMERG, \
1332 NOBUG_LOCATION_ARGS}); \
1333 NOBUG_BACKTRACE; \
1334 NOBUG_ABORT \
1339 //index.resource_dump xref:NOBUG_RESOURCE_DUMP[NOBUG_RESOURCE_DUMP]:: dump the state of a single resource
1340 //resourcemacros [[NOBUG_RESOURCE_DUMP]]
1341 //resourcemacros
1342 //resourcemacros .NOBUG_RESOURCE_DUMP
1343 //resourcemacros NOBUG_RESOURCE_DUMP(flag, handle)
1344 //resourcemacros
1345 //resourcemacros Dump the state of a single resource.
1346 //resourcemacros
1347 //resourcemacros `flag`::
1348 //resourcemacros Nobug flag for the log channel
1349 //resourcemacros `handle`::
1350 //resourcemacros handle of the resource to be dumped
1351 //resourcemacros
1353 #define NOBUG_RESOURCE_DUMP(flag, handle) \
1354 do { NOBUG_RESOURCE_LOCK; \
1355 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1356 {&NOBUG_FLAG(flag), \
1357 NOBUG_RESOURCE_LOG_LEVEL, \
1358 NOBUG_LOCATION_ARGS}); \
1359 NOBUG_RESOURCE_UNLOCK; } while (0)
1361 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle) \
1362 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1363 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1364 {&NOBUG_FLAG(flag), \
1365 NOBUG_RESOURCE_LOG_LEVEL, \
1366 NOBUG_LOCATION_ARGS}); \
1367 NOBUG_RESOURCE_UNLOCK)
1371 //index.resource_dumpall xref:NOBUG_RESOURCE_DUMPALL[NOBUG_RESOURCE_DUMPALL]:: dump the state of all resources
1372 //resourcemacros [[NOBUG_RESOURCE_DUMPALL]]
1373 //resourcemacros
1374 //resourcemacros .NOBUG_RESOURCE_DUMPALL
1375 //resourcemacros NOBUG_RESOURCE_DUMPALL(flag)
1376 //resourcemacros
1377 //resourcemacros Dump the state of all resources.
1378 //resourcemacros
1379 //resourcemacros `flag`::
1380 //resourcemacros Nobug flag for the log channel
1381 //resourcemacros
1383 #define NOBUG_RESOURCE_DUMPALL(flag) \
1384 do { NOBUG_RESOURCE_LOCK; \
1385 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1386 {&NOBUG_FLAG(flag), \
1387 NOBUG_RESOURCE_LOG_LEVEL, \
1388 NOBUG_LOCATION_ARGS}); \
1389 NOBUG_RESOURCE_UNLOCK; } while (0)
1392 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag) \
1393 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1394 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1395 {&NOBUG_FLAG(flag), \
1396 NOBUG_RESOURCE_LOG_LEVEL, \
1397 NOBUG_LOCATION_ARGS}); \
1398 NOBUG_RESOURCE_UNLOCK)
1402 //index.resource_list xref:NOBUG_RESOURCE_LIST[NOBUG_RESOURCE_LIST]:: enumerate all registered resources
1403 //resourcemacros [[NOBUG_RESOURCE_LIST]]
1404 //resourcemacros
1405 //resourcemacros .NOBUG_RESOURCE_LIST
1406 //resourcemacros NOBUG_RESOURCE_LIST(flag)
1407 //resourcemacros
1408 //resourcemacros List all registered resources.
1409 //resourcemacros
1410 //resourcemacros `flag`::
1411 //resourcemacros Nobug flag for the log channel
1412 //resourcemacros
1414 #define NOBUG_RESOURCE_LIST(flag) \
1415 do { NOBUG_RESOURCE_LOCK; \
1416 nobug_resource_list (&(struct nobug_resource_dump_context) \
1417 {&NOBUG_FLAG(flag), \
1418 NOBUG_RESOURCE_LOG_LEVEL, \
1419 NOBUG_LOCATION_ARGS}); \
1420 NOBUG_RESOURCE_UNLOCK; } while (0)
1422 #define NOBUG_RESOURCE_LIST_IF(when, flag) \
1423 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1424 nobug_resource_list (&(struct nobug_resource_dump_context) \
1425 {&NOBUG_FLAG(flag), \
1426 NOBUG_RESOURCE_LOG_LEVEL, \
1427 NOBUG_LOCATION_ARGS}); \
1428 NOBUG_RESOURCE_UNLOCK)
1432 threading support
1434 #if NOBUG_USE_PTHREAD
1435 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1436 #define NOBUG_THREAD_ID_FMT(pre,post) pre "%s" post
1437 #define NOBUG_THREAD_ID_COMMA , NOBUG_THREAD_ID_GET
1438 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1440 #else
1441 #define NOBUG_THREAD_ID_SET(name)
1442 #define NOBUG_THREAD_ID_FMT(pre,post) ""
1443 #define NOBUG_THREAD_ID_COMMA
1444 #define NOBUG_THREAD_ID_GET ""
1445 #endif
1449 Source location
1451 #define NOBUG_LOCATION_ARGS NOBUG_BASENAME(__FILE__), __LINE__, __func__
1452 #define NOBUG_LOCATION_INFO (NOBUG_LOCATION_ARGS)
1454 #define NOBUG_LOCATION_FILE(file, _1, _2) file
1455 #define NOBUG_LOCATION_LINE(_1, line, _2) line
1456 #define NOBUG_LOCATION_FUNC(_1, _2, func) func
1460 Debuggers
1463 #define NOBUG_DBG_NONE 0
1464 #define NOBUG_DBG_GDB 1
1465 #define NOBUG_DBG_VALGRIND 2
1467 #define NOBUG_ACTIVE_DBG \
1468 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1469 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1472 //index.backtrace xref:BACKTRACE[BACKTRACE]:: generate a backtrace
1473 //toolmacros [[BACKTRACE]]
1474 //toolmacros .BACKTRACE
1475 //toolmacros BACKTRACE
1476 //toolmacros
1477 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1478 //toolmacros This is automatically called when NoBug finds an error and is due
1479 //toolmacros to abort. But one might call it manually too.
1480 //toolmacros
1482 #define NOBUG_BACKTRACE \
1483 NOBUG_IF_ALPHA( \
1484 switch (NOBUG_ACTIVE_DBG) { \
1485 case NOBUG_DBG_VALGRIND: \
1486 NOBUG_BACKTRACE_VALGRIND; \
1487 break; \
1488 default: \
1489 NOBUG_BACKTRACE_GLIBC; \
1490 }) \
1491 NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC)
1493 #define NOBUG_BACKTRACE_DBG \
1494 NOBUG_IF_NOT_RELEASE( \
1495 switch (NOBUG_ACTIVE_DBG) { \
1496 case NOBUG_DBG_VALGRIND: \
1497 NOBUG_BACKTRACE_VALGRIND; \
1498 break; \
1501 #define NOBUG_BACKTRACE_GDB fprintf(stderr, "UNIMPLEMENTED : GDB Backtraces\n")
1503 #define NOBUG_BACKTRACE_VALGRIND \
1504 NOBUG_IF(NOBUG_USE_VALGRIND, \
1505 VALGRIND_PRINTF_BACKTRACE("BACKTRACE: %s@%d %s", \
1506 NOBUG_LOCATION_ARGS))
1509 #ifndef NOBUG_BACKTRACE_DEPTH
1510 #define NOBUG_BACKTRACE_DEPTH 256
1511 #endif
1513 #define NOBUG_BACKTRACE_GLIBC \
1514 NOBUG_IF_NOT_RELEASE( \
1515 NOBUG_IF(NOBUG_USE_EXECINFO, do { \
1516 NOBUG_LOG_(&nobug_flag_NOBUG_ON, LOG_NOTICE, NOBUG_LOCATION_INFO, "BACKTRACE"); \
1517 nobug_backtrace_glibc (); \
1518 } while (0)))
1522 init and other function wrapers
1524 #define NOBUG_INIT nobug_init()
1525 #define NOBUG_BASENAME(name) (strrchr((name), '/')?strrchr((name), '/') + 1 : (name))
1526 #define NOBUG_ABORT abort()
1530 short macros without NOBUG_
1532 #ifndef NOBUG_DISABLE_SHORTNAMES
1533 #ifndef REQUIRE
1534 #define REQUIRE NOBUG_REQUIRE
1535 #endif
1536 #ifndef REQUIRE_DBG
1537 #define REQUIRE_DBG NOBUG_REQUIRE_DBG
1538 #endif
1539 #ifndef REQUIRE_IF
1540 #define REQUIRE_IF NOBUG_REQUIRE_IF
1541 #endif
1542 #ifndef REQUIRE_IF_DBG
1543 #define REQUIRE_IF_DBG NOBUG_REQUIRE_IF_DBG
1544 #endif
1545 #ifndef ENSURE
1546 #define ENSURE NOBUG_ENSURE
1547 #endif
1548 #ifndef ENSURE_DBG
1549 #define ENSURE_DBG NOBUG_ENSURE_DBG
1550 #endif
1551 #ifndef ENSURE_IF
1552 #define ENSURE_IF NOBUG_ENSURE_IF
1553 #endif
1554 #ifndef ENSURE_IF_DBG
1555 #define ENSURE_IF_DBG NOBUG_ENSURE_IF_DBG
1556 #endif
1557 #ifndef ASSERT
1558 #define ASSERT NOBUG_ASSERT
1559 #endif
1560 #ifndef ASSERT_DBG
1561 #define ASSERT_DBG NOBUG_ASSERT_DBG
1562 #endif
1563 #ifndef ASSERT_IF
1564 #define ASSERT_IF NOBUG_ASSERT_IF
1565 #endif
1566 #ifndef ASSERT_IF_DBG
1567 #define ASSERT_IF_DBG NOBUG_ASSERT_IF_DBG
1568 #endif
1569 #ifndef CHECK
1570 #define CHECK NOBUG_CHECK
1571 #endif
1572 #ifndef CHECK
1573 #define CHECK NOBUG_CHECK
1574 #endif
1575 #ifndef INVARIANT
1576 #define INVARIANT NOBUG_INVARIANT
1577 #endif
1578 #ifndef INVARIANT_DBG
1579 #define INVARIANT_DBG NOBUG_INVARIANT_DBG
1580 #endif
1581 #ifndef INVARIANT_IF
1582 #define INVARIANT_IF NOBUG_INVARIANT_IF
1583 #endif
1584 #ifndef INVARIANT_IF_DBG
1585 #define INVARIANT_IF_DBG NOBUG_INVARIANT_IF_DBG
1586 #endif
1587 #ifndef INVARIANT_ASSERT
1588 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
1589 #endif
1590 #ifndef DUMP
1591 #define DUMP NOBUG_DUMP
1592 #endif
1593 #ifndef DUMP_DBG
1594 #define DUMP_DBG NOBUG_DUMP_DBG
1595 #endif
1596 #ifndef DUMP_IF
1597 #define DUMP_IF NOBUG_DUMP_IF
1598 #endif
1599 #ifndef DUMP_IF_DBG
1600 #define DUMP_IF_DBG NOBUG_DUMP_IF_DBG
1601 #endif
1602 #ifndef DUMP_LOG
1603 #define DUMP_LOG NOBUG_DUMP_LOG
1604 #endif
1605 #ifndef DUMP_LOG_DBG
1606 #define DUMP_LOG_DBG NOBUG_DUMP_LOG_DBG
1607 #endif
1608 #ifndef DUMP_LOG_IF
1609 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1610 #endif
1611 #ifndef DUMP_LOG_IF_DBG
1612 #define DUMP_LOG_IF_DBG NOBUG_DUMP_LOG_IF_DBG
1613 #endif
1614 #ifndef LOG
1615 #define LOG NOBUG_LOG
1616 #endif
1617 #ifndef LOG_DBG
1618 #define LOG_DBG NOBUG_LOG_DBG
1619 #endif
1620 #ifndef LOG_IF
1621 #define LOG_IF NOBUG_LOG_IF
1622 #endif
1623 #ifndef LOG_IF_DBG
1624 #define LOG_IF_DBG NOBUG_LOG_IF_DBG
1625 #endif
1626 #ifndef ECHO
1627 #define ECHO NOBUG_ECHO
1628 #endif
1629 #ifndef ALERT
1630 #define ALERT NOBUG_ALERT
1631 #endif
1632 #ifndef ALERT_DBG
1633 #define ALERT_DBG NOBUG_ALERT_DBG
1634 #endif
1635 #ifndef ALERT_IF
1636 #define ALERT_IF NOBUG_ALERT_IF
1637 #endif
1638 #ifndef ALERT_IF_DBG
1639 #define ALERT_IF_DBG NOBUG_ALERT_IF_DBG
1640 #endif
1641 #ifndef CRITICAL
1642 #define CRITICAL NOBUG_CRITICAL
1643 #endif
1644 #ifndef CRITICAL_DBG
1645 #define CRITICAL_DBG NOBUG_CRITICAL_DBG
1646 #endif
1647 #ifndef CRITICAL_IF
1648 #define CRITICAL_IF NOBUG_CRITICAL_IF
1649 #endif
1650 #ifndef CRITICAL_IF_DBG
1651 #define CRITICAL_IF_DBG NOBUG_CRITICAL_IF_DBG
1652 #endif
1653 #ifndef ERROR
1654 #define ERROR NOBUG_ERROR
1655 #endif
1656 #ifndef ERROR_DBG
1657 #define ERROR_DBG NOBUG_ERROR_DBG
1658 #endif
1659 #ifndef ERROR_IF
1660 #define ERROR_IF NOBUG_ERROR_IF
1661 #endif
1662 #ifndef ERROR_IF_DBG
1663 #define ERROR_IF_DBG NOBUG_ERROR_IF_DBG
1664 #endif
1665 #ifndef WARN
1666 #define WARN NOBUG_WARN
1667 #endif
1668 #ifndef WARN_DBG
1669 #define WARN_DBG NOBUG_WARN_DBG
1670 #endif
1671 #ifndef WARN_IF
1672 #define WARN_IF NOBUG_WARN_IF
1673 #endif
1674 #ifndef WARN_IF_DBG
1675 #define WARN_IF_DBG NOBUG_WARN_IF_DBG
1676 #endif
1677 #ifndef INFO
1678 #define INFO NOBUG_INFO
1679 #endif
1680 #ifndef INFO_DBG
1681 #define INFO_DBG NOBUG_INFO_DBG
1682 #endif
1683 #ifndef INFO_IF
1684 #define INFO_IF NOBUG_INFO_IF
1685 #endif
1686 #ifndef INFO_IF_DBG
1687 #define INFO_IF_DBG NOBUG_INFO_IF_DBG
1688 #endif
1689 #ifndef NOTICE
1690 #define NOTICE NOBUG_NOTICE
1691 #endif
1692 #ifndef NOTICE_DBG
1693 #define NOTICE_DBG NOBUG_NOTICE_DBG
1694 #endif
1695 #ifndef NOTICE_IF
1696 #define NOTICE_IF NOBUG_NOTICE_IF
1697 #endif
1698 #ifndef NOTICE_IF_DBG
1699 #define NOTICE_IF_DBG NOBUG_NOTICE_IF_DBG
1700 #endif
1701 #ifndef TRACE
1702 #define TRACE NOBUG_TRACE
1703 #endif
1704 #ifndef TRACE_DBG
1705 #define TRACE_DBG NOBUG_TRACE_DBG
1706 #endif
1707 #ifndef TRACE_IF
1708 #define TRACE_IF NOBUG_TRACE_IF
1709 #endif
1710 #ifndef TRACE_IF_DBG
1711 #define TRACE_IF_DBG NOBUG_TRACE_IF_DBG
1712 #endif
1713 #ifndef BACKTRACE
1714 #define BACKTRACE NOBUG_BACKTRACE
1715 #endif
1716 #ifndef BACKTRACE_DBG
1717 #define BACKTRACE_DBG NOBUG_BACKTRACE_DBG
1718 #endif
1719 #ifndef DEPRECATED
1720 #define DEPRECATED NOBUG_DEPRECATED
1721 #endif
1722 #ifndef UNIMPLEMENTED
1723 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1724 #endif
1725 #ifndef FIXME
1726 #define FIXME NOBUG_FIXME
1727 #endif
1728 #ifndef TODO
1729 #define TODO NOBUG_TODO
1730 #endif
1731 #ifndef PLANNED
1732 #define PLANNED NOBUG_PLANNED
1733 #endif
1734 #ifndef NOTREACHED
1735 #define NOTREACHED NOBUG_NOTREACHED
1736 #endif
1737 #ifndef INJECT_GOODBAD
1738 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
1739 #endif
1740 #ifndef INJECT_FAULT
1741 #define INJECT_FAULT NOBUG_INJECT_FAULT
1742 #endif
1743 #ifndef CLEANUP
1744 #define CLEANUP NOBUG_CLEANUP
1745 #endif
1746 #ifndef CHECKED
1747 #define CHECKED NOBUG_CHECKED
1748 #endif
1749 #ifndef UNCHECKED
1750 #define UNCHECKED NOBUG_UNCHECKED
1751 #endif
1752 #ifndef RESOURCE_ANNOUNCE
1753 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1754 #endif
1755 #ifndef RESOURCE_FORGET
1756 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1757 #endif
1758 #ifndef RESOURCE_ENTER
1759 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1760 #endif
1761 #ifndef RESOURCE_STATE
1762 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1763 #endif
1764 #ifndef RESOURCE_LEAVE
1765 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1766 #endif
1767 #ifndef RESOURCE_LEAVE_LOOKUP
1768 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1769 #endif
1770 #ifndef RESOURCE_HANDLE
1771 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1772 #endif
1773 #ifndef RESOURCE_HANDLE_INIT
1774 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
1775 #endif
1776 #ifndef RESOURCE_DUMP
1777 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
1778 #endif
1779 #ifndef RESOURCE_DUMP_IF
1780 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
1781 #endif
1782 #ifndef RESOURCE_DUMPALL
1783 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
1784 #endif
1785 #ifndef RESOURCE_DUMPALL_IF
1786 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
1787 #endif
1788 #ifndef RESOURCE_LIST
1789 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
1790 #endif
1791 #ifndef RESOURCE_LIST_IF
1792 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
1793 #endif
1794 #endif /* NOBUG_DISABLE_SHORTNAMES */
1798 Tool macros
1800 #ifdef __GNUC__
1801 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
1802 #else
1803 #define NOBUG_CLEANUP(fn)
1804 #endif
1807 //index.comma xref:NOBUG_ALPHA_COMMA[NOBUG_ALPHA_COMMA]:: append something after a comma in *ALPHA* builds
1808 //toolmacros [[NOBUG_ALPHA_COMMA]]
1809 //toolmacros .NOBUG_ALPHA_COMMA
1810 //toolmacros NOBUG_ALPHA_COMMA(something)
1811 //toolmacros NOBUG_ALPHA_COMMA_NULL
1812 //toolmacros
1813 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
1814 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
1815 //toolmacros use this macros to append a comman and something else only in *ALPHA* builds as in:
1816 //toolmacros struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
1817 //toolmacros
1819 #define NOBUG_COMMA ,
1820 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
1821 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
1823 #define NOBUG_ONCE(code) \
1824 do { \
1825 static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 0; \
1826 if (NOBUG_EXPECT_FALSE(!NOBUG_CAT(nobug_once_,__LINE__))) \
1828 NOBUG_CAT(nobug_once_,__LINE__) = 1; \
1829 code; \
1831 } while (0)
1833 #if __GNUC__
1834 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
1835 #else
1836 #define NOBUG_EXPECT_FALSE(x) x
1837 #endif
1839 #define NOBUG_WHEN(when, ...) \
1840 do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
1843 //index.if xref:NOBUG_IF[NOBUG_IF_*]:: include code conditionally on build level
1844 //toolmacros [[NOBUG_IF]]
1845 //toolmacros .NOBUG_IF_*
1846 //toolmacros NOBUG_IF_ALPHA(...)
1847 //toolmacros NOBUG_IF_NOT_ALPHA(...)
1848 //toolmacros NOBUG_IF_BETA(...)
1849 //toolmacros NOBUG_IF_NOT_BETA(...)
1850 //toolmacros NOBUG_IF_RELEASE(...)
1851 //toolmacros NOBUG_IF_NOT_RELEASE(...)
1852 //toolmacros
1853 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
1854 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
1855 //toolmacros internally, but can also be used for custom things.
1856 //toolmacros
1858 #define NOBUG_IF_ALPHA(...) \
1859 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1861 #define NOBUG_IF_NOT_ALPHA(...) \
1862 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1864 #define NOBUG_IF_BETA(...) \
1865 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__) \
1867 #define NOBUG_IF_NOT_BETA(...) \
1868 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__) \
1870 #define NOBUG_IF_RELEASE(...) \
1871 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1873 #define NOBUG_IF_NOT_RELEASE(...) \
1874 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1877 preprocessor hacks/metaprogramming
1880 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
1881 #define NOBUG_IF_1(...) __VA_ARGS__
1882 #define NOBUG_IF_0(...)
1884 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
1886 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
1887 #define NOBUG_NOT_1 0
1888 #define NOBUG_NOT_0 1
1890 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
1891 #define NOBUG_AND_00 0
1892 #define NOBUG_AND_01 0
1893 #define NOBUG_AND_10 0
1894 #define NOBUG_AND_11 1
1896 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
1897 #define NOBUG_OR_00 0
1898 #define NOBUG_OR_01 1
1899 #define NOBUG_OR_10 1
1900 #define NOBUG_OR_11 1
1902 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
1903 #define NOBUG_XOR_00 0
1904 #define NOBUG_XOR_01 1
1905 #define NOBUG_XOR_10 1
1906 #define NOBUG_XOR_11 0
1908 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
1909 #define NOBUG_CAT_(a,b) a##b
1911 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
1912 #define NOBUG_CAT3_(a,b,c) a##b##c
1914 #define NOBUG_HEAD(head, ...) head
1915 #define NOBUG_TAIL(_, ...) , ## __VA_ARGS__
1917 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
1918 #define NOBUG_STRINGIZE_(s) #s
1922 LIBNOBUG DECLARATIONS
1924 #ifdef __cplusplus
1925 extern "C" {
1926 #endif
1929 envvar control
1931 enum nobug_log_targets
1933 NOBUG_TARGET_RINGBUFFER,
1934 NOBUG_TARGET_CONSOLE,
1935 NOBUG_TARGET_FILE,
1936 NOBUG_TARGET_SYSLOG,
1937 NOBUG_TARGET_APPLICATION
1940 struct nobug_flag
1942 const char* name;
1943 struct nobug_flag* parent;
1944 volatile int initialized;
1945 int limits[5];
1946 struct nobug_ringbuffer* ringbuffer_target;
1947 FILE* console_target;
1948 FILE* file_target;
1952 nobug_env_parse_flag (const char* env, struct nobug_flag* flag, int default_target, int default_limit);
1955 nobug_env_init_flag (struct nobug_flag* flag, int default_target, int default_limit);
1959 ringbuffer
1961 struct nobug_ringbuffer
1963 char* pos;
1964 char* start;
1965 size_t size;
1966 size_t maxmsg;
1967 char name[256];
1970 enum nobug_ringbuffer_flags
1972 NOBUG_RINGBUFFER_DEFAULT, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
1973 NOBUG_RINGBUFFER_APPEND = 1, /* use existing backing file, append if possible */
1974 NOBUG_RINGBUFFER_TEMP = 2, /* unlink file instantly */
1975 NOBUG_RINGBUFFER_KEEP = 4 /* dont unlink the file at destroy */
1979 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
1980 with sane (but undefined) semantics.
1982 struct nobug_ringbuffer*
1983 nobug_ringbuffer_init (struct nobug_ringbuffer* self, size_t size,
1984 const char * name, int flags);
1986 struct nobug_ringbuffer*
1987 nobug_ringbuffer_new (size_t size, const char * name, int flags);
1989 struct nobug_ringbuffer*
1990 nobug_ringbuffer_destroy (struct nobug_ringbuffer* self);
1992 void
1993 nobug_ringbuffer_delete (struct nobug_ringbuffer* self);
1996 nobug_ringbuffer_vprintf (struct nobug_ringbuffer* self, const char* fmt, va_list ap);
1999 nobug_ringbuffer_printf (struct nobug_ringbuffer* self, const char* fmt, ...);
2001 char*
2002 nobug_ringbuffer_prev (struct nobug_ringbuffer* self, char* pos);
2004 char*
2005 nobug_ringbuffer_next (struct nobug_ringbuffer* self, char* pos);
2008 nobug_ringbuffer_save (struct nobug_ringbuffer* self, FILE* out);
2011 nobug_ringbuffer_load (struct nobug_ringbuffer* self, FILE* in);
2013 char*
2014 nobug_ringbuffer_pos (struct nobug_ringbuffer* self);
2016 void
2017 nobug_ringbuffer_pop (struct nobug_ringbuffer* self);
2021 multithreading extras
2023 #if NOBUG_USE_PTHREAD
2025 struct nobug_tls_data
2027 const char * thread_id;
2028 struct nobug_resource_record* lock_stack;
2031 extern pthread_key_t nobug_tls_key;
2033 const char*
2034 nobug_thread_id_set (const char* name);
2036 const char*
2037 nobug_thread_id_get (void);
2039 extern pthread_mutex_t nobug_logging_mutex;
2040 extern pthread_mutex_t nobug_resource_mutex;
2041 #endif
2045 resource registry
2048 #ifndef LLIST_DEFINED
2049 #define LLIST_DEFINED
2050 struct llist_struct
2052 struct llist_struct *next;
2053 struct llist_struct *prev;
2055 #endif
2057 #if NOBUG_USE_PTHREAD
2058 #define NOBUG_RESOURCE_LOCK pthread_mutex_lock (&nobug_resource_mutex)
2059 #define NOBUG_RESOURCE_UNLOCK pthread_mutex_unlock (&nobug_resource_mutex)
2061 Note: errors are all fatal, we dont unlock the mutex when returning an error,
2062 this should be handled better in future but does not hurt
2064 #else
2065 #define NOBUG_RESOURCE_LOCK
2066 #define NOBUG_RESOURCE_UNLOCK
2067 #endif
2070 enum nobug_resource_state
2072 NOBUG_RESOURCE_INVALID,
2073 NOBUG_RESOURCE_WAITING,
2074 NOBUG_RESOURCE_EXCLUSIVE,
2075 NOBUG_RESOURCE_RECURSIVE,
2076 NOBUG_RESOURCE_SHARED,
2079 struct nobug_resource_header
2081 struct llist_struct node; /* link node for resource registry, users and pool list */
2082 const char* name; /* name */
2083 const char* extra; /* extra information, file/line usually */
2087 struct nobug_resource_record
2089 struct nobug_resource_header hdr;
2090 struct llist_struct users; /* list of users of this resource */
2091 const void* object_id; /* unique identifer, usually a this pointer or similar */
2092 const char* type; /* type */
2094 struct nobug_resource_record* prev; /* higher or same precedence resources */
2095 struct nobug_resource_record* skip; /* higher precedence */
2098 struct nobug_resource_user
2100 struct nobug_resource_header hdr;
2101 #if NOBUG_USE_PTHREAD
2102 const void* thread_id; /* pointer to this theads id */
2103 #endif
2104 struct nobug_resource_user* lock_stack; /* locks in use of this thread */
2105 struct nobug_resource_record* resource; /* associated resource */
2106 enum nobug_resource_state state; /* state */
2110 extern const char* nobug_resource_error;
2112 extern const char* nobug_resource_states[];
2114 struct nobug_resource_record*
2115 nobug_resource_announce (const char* type, const char* name, const void* object_id, const char* extra);
2118 nobug_resource_forget (struct nobug_resource_record* node);
2120 struct nobug_resource_user*
2121 nobug_resource_enter (struct nobug_resource_record* resource,
2122 const char* name,
2123 enum nobug_resource_state state,
2124 const char* extra);
2127 nobug_resource_state (struct nobug_resource_user* resource,
2128 enum nobug_resource_state state);
2131 nobug_resource_leave (struct nobug_resource_user* handle);
2134 struct nobug_resource_dump_context
2136 struct nobug_flag* flag;
2137 int level;
2138 const char* file;
2139 int line;
2140 const char* func;
2143 void
2144 nobug_resource_dump (struct nobug_resource_record* resource, struct nobug_resource_dump_context* context);
2146 void
2147 nobug_resource_dump_all (struct nobug_resource_dump_context* context);
2149 void
2150 nobug_resource_list (struct nobug_resource_dump_context* context);
2154 global config, data and defaults
2156 extern const char* nobug_resource_acquired;
2158 void nobug_init (void);
2160 void
2161 nobug_backtrace_glibc (void);
2163 void
2164 nobug_log (struct nobug_flag* flag, int lvl, const char* fmt, ...);
2166 typedef void (*nobug_application_cb)(struct nobug_flag* flag, int priority, const char *log, void* data);
2168 extern struct nobug_ringbuffer nobug_default_ringbuffer;
2169 extern FILE* nobug_default_file;
2170 extern struct nobug_flag nobug_flag_NOBUG_ON;
2171 extern struct nobug_flag nobug_flag_NOBUG_ANN;
2172 extern struct nobug_flag nobug_flag_nobug;
2173 extern unsigned long long nobug_counter;
2174 extern nobug_application_cb nobug_callback;
2175 extern void* nobug_callback_data;
2177 #ifdef __cplusplus
2178 } /* extern "C" */
2179 #endif
2181 #ifndef NOBUG_LIBNOBUG_C
2184 tag this translation unit as unchecked in ALPHA and BETA builds
2186 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED);
2188 #endif /* NOBUG_LIBNOBUG_C */
2189 #endif