]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Enable tracking of pthreads barriers
authorMichał Kępień <michal@isc.org>
Wed, 13 Jul 2022 11:19:32 +0000 (13:19 +0200)
committerMichał Kępień <michal@isc.org>
Wed, 13 Jul 2022 11:19:32 +0000 (13:19 +0200)
Some POSIX threads implementations (e.g. FreeBSD's libthr) allocate
memory on the heap when pthread_barrier_init() is called.  Every call to
that function must be accompanied by a corresponding call to
pthread_barrier_destroy() or else the memory allocated for the barrier
will leak.

jemalloc can be used for detecting memory allocations which are not
released by a process when it exits.  Unfortunately, since jemalloc is
also the system allocator on FreeBSD and a special (profiling-enabled)
build of jemalloc is required for memory leak detection, this method
cannot be used for detecting leaked memory allocated by libthr on a
stock FreeBSD installation.

However, libthr's behavior can be emulated on any platform by
implementing alternative versions of libisc functions for creating and
destroying barriers that allocate memory using malloc() and release it
using free().  This enables using jemalloc for detecting missing
pthread_barrier_destroy() calls on any platform on which it works
reliably.

When the newly introduced ISC_TRACK_PTHREADS_OBJECTS preprocessor macro
is set, allocate isc_barrier_t structures on the heap in
isc_barrier_init() and free them in isc_barrier_destroy().  Reuse
existing barrier macros (after renaming them appropriately) for other
operations.

lib/isc/include/isc/barrier.h

index 74e63276817b1d3a1c7f1119f391098132213d2a..20bfdab0acde91d21c312bee106541ceb95a92ab 100644 (file)
 #define isc_barrier_destroy(barrier) pthread_barrier_destroy(barrier)
 #define isc_barrier_wait(barrier)    pthread_barrier_wait(barrier)
 
-#else
+#else /* __SANITIZE_THREAD__ */
 
 #include <isc/uv.h>
 
-#define isc_barrier_t uv_barrier_t
+#if ISC_TRACK_PTHREADS_OBJECTS
 
-#define isc_barrier_init(barrier, count) uv_barrier_init(barrier, count)
-#define isc_barrier_destroy(barrier)    uv_barrier_destroy(barrier)
-#define isc_barrier_wait(barrier)       uv_barrier_wait(barrier)
+typedef uv_barrier_t *isc_barrier_t;
+
+#define isc_barrier_init(bp, count)            \
+       {                                      \
+               *bp = malloc(sizeof(**bp));    \
+               isc__barrier_init(*bp, count); \
+       }
+#define isc_barrier_wait(bp) isc__barrier_wait(*bp)
+#define isc_barrier_destroy(bp)            \
+       {                                  \
+               isc__barrier_destroy(*bp); \
+               free(*bp);                 \
+       }
+
+#else /* ISC_TRACK_PTHREADS_OBJECTS */
+
+typedef uv_barrier_t isc_barrier_t;
+
+#define isc_barrier_init(bp, count) isc__barrier_init(bp, count)
+#define isc_barrier_wait(bp)       isc__barrier_wait(bp)
+#define isc_barrier_destroy(bp)            isc__barrier_destroy(bp)
+
+#endif /* ISC_TRACK_PTHREADS_OBJECTS */
+
+#define isc__barrier_init(bp, count) uv_barrier_init(bp, count)
+#define isc__barrier_wait(bp)       uv_barrier_wait(bp)
+#define isc__barrier_destroy(bp)     uv_barrier_destroy(bp)
 
 #endif /* __SANITIZE_THREAD__ */