]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Replace attach/detach in isc_mem with refcount implementation
authorOndřej Surý <ondrej@isc.org>
Mon, 9 Sep 2024 10:14:05 +0000 (12:14 +0200)
committerOndřej Surý <ondrej@isc.org>
Wed, 5 Mar 2025 10:17:17 +0000 (11:17 +0100)
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.

lib/isc/include/isc/mem.h
lib/isc/mem.c

index ad3b4bd97a8a25f450f96d64805b20b41a0d85c6..9f44628d0143bbbc811038b28c66b98afb26be85 100644 (file)
 #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);
index 4fb27ad23d2c20551d06e4fff041bde2c57057d9..5edf15a8f6b1c95622df3a8ef54ee58134dde5a3 100644 (file)
@@ -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 *