Replace attach/detach in isc_mem with refcount implementation
The isc_mem API is one of the most commonly used APIs that didn't used ISC_REFCOUNT_DECL and ISC_REFCOUNT_IMPL macros. Replace the implementation of isc_mem_attach(), isc_mem_detach() and isc_mem_destroy() with the respective macros. This also removes the legacy isc_mem_destroy() functionality that would check whether all references had been detached from the memory context as it doesn't work reliably when using the call_rcu() API. Instead of doing this individually, call isc_mem_checkdestroyed(stderr) from the isc_mem_destroy() macro to keep the extra check that all contexts were freed when the program is exiting.
This commit is contained in:
@@ -21,9 +21,12 @@
|
||||
#include <isc/attributes.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/overflow.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/types.h>
|
||||
#include <isc/urcu.h>
|
||||
|
||||
/* 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);
|
||||
|
||||
@@ -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 *
|
||||
|
||||
Reference in New Issue
Block a user