#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.
*/
/*@}*/
-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);
isc__mem_shutdown(void) {
bool empty;
+ rcu_barrier();
+
isc__mem_checkdestroyed();
LOCK(&contextslock);
*/
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);
}
}
-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:
*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 *