diff --git a/lib/isc/include/isc/mem.h b/lib/isc/include/isc/mem.h index ad3b4bd97a..9f44628d01 100644 --- a/lib/isc/include/isc/mem.h +++ b/lib/isc/include/isc/mem.h @@ -21,9 +21,12 @@ #include #include #include +#include #include #include +/* Add -DISC_MEM_TRACE=1 to CFLAGS for detailed reference tracing */ + /*% * Define ISC_MEM_TRACKLINES=1 to turn on detailed tracing of memory * allocation and freeing by file and line number. @@ -249,28 +252,16 @@ isc_mem_arena_set_dirty_decay_ms(isc_mem_t *mctx, const ssize_t decay_ms); */ /*@}*/ -void -isc_mem_attach(isc_mem_t *, isc_mem_t **); - -/*@{*/ -void -isc_mem_attach(isc_mem_t *, isc_mem_t **); -#define isc_mem_detach(cp) isc__mem_detach((cp)_ISC_MEM_FILELINE) -void -isc__mem_detach(isc_mem_t **_ISC_MEM_FLARG); -/*!< - * \brief Attach to / detach from a memory context. - * - * This is intended for applications that use multiple memory contexts - * in such a way that it is not obvious when the last allocations from - * a given context has been freed and destroying the context is safe. - * - * Most applications do not need to call these functions as they can - * simply create a single memory context at the beginning of main() - * and destroy it at the end of main(), thereby guaranteeing that it - * is not destroyed while there are outstanding allocations. - */ -/*@}*/ +#if ISC_MEM_TRACE +#define isc_mem_ref(ptr) isc_mem__ref(ptr, __func__, __FILE__, __LINE__) +#define isc_mem_unref(ptr) isc_mem__unref(ptr, __func__, __FILE__, __LINE__) +#define isc_mem_attach(ptr, ptrp) \ + isc_mem__attach(ptr, ptrp, __func__, __FILE__, __LINE__) +#define isc_mem_detach(ptrp) isc_mem__detach(ptrp, __func__, __FILE__, __LINE__) +ISC_REFCOUNT_TRACE_DECL(isc_mem); +#else +ISC_REFCOUNT_DECL(isc_mem); +#endif void isc_mem_stats(isc_mem_t *mctx, FILE *out); diff --git a/lib/isc/mem.c b/lib/isc/mem.c index 4fb27ad23d..5edf15a8f6 100644 --- a/lib/isc/mem.c +++ b/lib/isc/mem.c @@ -427,6 +427,8 @@ void isc__mem_shutdown(void) { bool empty; + rcu_barrier(); + isc__mem_checkdestroyed(); LOCK(&contextslock); @@ -495,8 +497,11 @@ mem_create(isc_mem_t **ctxp, unsigned int debugging, unsigned int flags, */ static void -destroy(isc_mem_t *ctx) { +mem_destroy(isc_mem_t *ctx) { unsigned int arena_no; + + isc_refcount_destroy(&ctx->references); + LOCK(&contextslock); ISC_LIST_UNLINK(contexts, ctx, link); UNLOCK(&contextslock); @@ -543,36 +548,11 @@ destroy(isc_mem_t *ctx) { } } -void -isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) { - REQUIRE(VALID_CONTEXT(source)); - REQUIRE(targetp != NULL && *targetp == NULL); - - isc_refcount_increment(&source->references); - - *targetp = source; -} - -void -isc__mem_detach(isc_mem_t **ctxp FLARG) { - isc_mem_t *ctx = NULL; - - REQUIRE(ctxp != NULL && VALID_CONTEXT(*ctxp)); - - ctx = *ctxp; - *ctxp = NULL; - - if (isc_refcount_decrement(&ctx->references) == 1) { - isc_refcount_destroy(&ctx->references); -#if ISC_MEM_TRACKLINES - if ((ctx->debugging & ISC_MEM_DEBUGTRACE) != 0) { - fprintf(stderr, "destroy mctx %p file %s line %u\n", - ctx, file, line); - } +#if ISC_MEM_TRACE +ISC_REFCOUNT_TRACE_IMPL(isc_mem, mem_destroy); +#else +ISC_REFCOUNT_IMPL(isc_mem, mem_destroy); #endif - destroy(ctx); - } -} /* * isc_mem_putanddetach() is the equivalent of: @@ -595,7 +575,11 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size, *ctxp = NULL; isc__mem_put(ctx, ptr, size, flags FLARG_PASS); - isc__mem_detach(&ctx FLARG_PASS); +#if ISC_MEM_TRACE + isc_mem__detach(&ctx, __func__, file, line); +#else + isc_mem_detach(&ctx); +#endif } void *