]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add isc_mem_reget() function to realloc isc_mem_get allocations
authorOndřej Surý <ondrej@isc.org>
Wed, 22 Sep 2021 16:48:03 +0000 (18:48 +0200)
committerEvan Hunt <each@isc.org>
Thu, 23 Sep 2021 18:18:07 +0000 (11:18 -0700)
The isc_mem_get() and isc_mem_put() functions are leaving the memory
allocation size tracking to the users of the API, while
isc_mem_allocate() and isc_mem_free() would track the sizes internally.
This allowed to have isc_mem_rellocate() to manipulate the memory
allocations by the later set, but not the former set of the functions.

This commit introduces isc_mem_reget(ctx, old_ptr, old_size, new_size)
function that operates on the memory allocations with external size
tracking completing the API.

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

index 0e0d24a3b16f9ec5bdc8a2721d193ea5fb3e1cd0..a513890cc75386930d781024c5c240a4cafae53e 100644 (file)
@@ -134,7 +134,9 @@ extern unsigned int isc_mem_defaultflags;
 #define ISCMEMFUNC(sfx)            isc__mem_##sfx
 #define ISCMEMPOOLFUNC(sfx) isc__mempool_##sfx
 
-#define isc_mem_get(c, s)      ISCMEMFUNC(get)((c), (s)_ISC_MEM_FILELINE)
+#define isc_mem_get(c, s) ISCMEMFUNC(get)((c), (s)_ISC_MEM_FILELINE)
+#define isc_mem_reget(c, p, o, n) \
+       ISCMEMFUNC(reget)((c), (p), (o), (n)_ISC_MEM_FILELINE)
 #define isc_mem_allocate(c, s) ISCMEMFUNC(allocate)((c), (s)_ISC_MEM_FILELINE)
 #define isc_mem_reallocate(c, p, s) \
        ISCMEMFUNC(reallocate)((c), (p), (s)_ISC_MEM_FILELINE)
@@ -483,6 +485,9 @@ void ISCMEMFUNC(free)(isc_mem_t *, void *_ISC_MEM_FLARG);
 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(put), 2)
 void *ISCMEMFUNC(get)(isc_mem_t *, size_t _ISC_MEM_FLARG);
 
+ISC_ATTR_DEALLOCATOR_IDX(ISCMEMFUNC(put), 2)
+void *ISCMEMFUNC(reget)(isc_mem_t *, void *, size_t, size_t _ISC_MEM_FLARG);
+
 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2)
 void *ISCMEMFUNC(allocate)(isc_mem_t *, size_t _ISC_MEM_FLARG);
 
index e598afce8b0c9303e38f6d1cb759390fc9a1d69b..c368959fa7e2056c64c8de7625f8d02f38ea1c05 100644 (file)
@@ -349,6 +349,24 @@ mem_put(isc_mem_t *ctx, void *mem, size_t size) {
        sdallocx(mem, size, 0);
 }
 
+static inline void *
+mem_realloc(isc_mem_t *ctx, void *old_ptr, size_t old_size, size_t new_size) {
+       void *new_ptr = NULL;
+
+       new_ptr = rallocx(old_ptr, new_size, 0);
+
+       if (ISC_UNLIKELY((ctx->flags & ISC_MEMFLAG_FILL) != 0)) {
+               ssize_t diff_size = new_size - old_size;
+               void *diff_ptr = (uint8_t *)new_ptr + old_size;
+               if (diff_size > 0) {
+                       /* Mnemonic for "beef". */
+                       memset(diff_ptr, 0xbe, diff_size);
+               }
+       }
+
+       return (new_ptr);
+}
+
 #define stats_bucket(ctx, size)                      \
        ((size / STATS_BUCKET_SIZE) >= STATS_BUCKETS \
                 ? &ctx->stats[STATS_BUCKETS]        \
@@ -872,6 +890,37 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
        return (ptr);
 }
 
+void *
+isc__mem_reget(isc_mem_t *ctx, void *old_ptr, size_t old_size,
+              size_t new_size FLARG) {
+       void *new_ptr = NULL;
+
+       if (ISC_UNLIKELY(old_ptr == NULL)) {
+               REQUIRE(old_size == 0);
+               new_ptr = isc__mem_get(ctx, new_size FLARG_PASS);
+       } else if (ISC_UNLIKELY(new_size == 0)) {
+               isc__mem_put(ctx, old_ptr, old_size FLARG_PASS);
+       } else {
+               DELETE_TRACE(ctx, old_ptr, old_size, file, line);
+               mem_putstats(ctx, old_ptr, old_size);
+
+               new_ptr = mem_realloc(ctx, old_ptr, old_size, new_size);
+
+               mem_getstats(ctx, new_size);
+               ADD_TRACE(ctx, new_ptr, new_size, file, line);
+
+               /*
+                * We want to postpone the call to water in edge case
+                * where the realloc will exactly hit on the boundary of
+                * the water and we would call water twice.
+                */
+               CALL_LO_WATER(ctx);
+               CALL_HI_WATER(ctx);
+       }
+
+       return (new_ptr);
+}
+
 void *
 isc__mem_reallocate(isc_mem_t *ctx, void *old_ptr, size_t new_size FLARG) {
        void *new_ptr = NULL;
@@ -888,16 +937,7 @@ isc__mem_reallocate(isc_mem_t *ctx, void *old_ptr, size_t new_size FLARG) {
                DELETE_TRACE(ctx, old_ptr, old_size, file, line);
                mem_putstats(ctx, old_ptr, old_size);
 
-               new_ptr = rallocx(old_ptr, new_size, 0);
-
-               if (ISC_UNLIKELY((ctx->flags & ISC_MEMFLAG_FILL) != 0)) {
-                       ssize_t diff_size = new_size - old_size;
-                       void *diff_ptr = (uint8_t *)new_ptr + old_size;
-                       if (diff_size >= 0) {
-                               /* Mnemonic for "beef". */
-                               memset(diff_ptr, 0xbe, diff_size);
-                       }
-               }
+               new_ptr = mem_realloc(ctx, old_ptr, old_size, new_size);
 
                /* Recalculate the real allocated size */
                new_size = sallocx(new_ptr, 0);
index e848200e2adbb7d9d1b150da72cf5a58044e074a..d5b46f2a1b03cb540e6f39146ab81ab71da12e81 100644 (file)
@@ -220,6 +220,40 @@ isc_mem_inuse_test(void **state) {
        isc_mem_destroy(&mctx2);
 }
 
+#define REGET_INIT_SIZE          1024
+#define REGET_GROW_SIZE          2048
+#define REGET_SHRINK_SIZE 512
+
+static void
+isc_mem_reget_test(void **state) {
+       uint8_t *data = isc_mem_get(test_mctx, REGET_INIT_SIZE);
+
+       UNUSED(state);
+
+       for (size_t i = 0; i < REGET_INIT_SIZE; i++) {
+               data[i] = i % UINT8_MAX;
+       }
+
+       data = isc_mem_reget(test_mctx, data, REGET_INIT_SIZE, REGET_GROW_SIZE);
+
+       for (size_t i = 0; i < REGET_INIT_SIZE; i++) {
+               assert_int_equal(data[i], i % UINT8_MAX);
+       }
+
+       for (size_t i = REGET_GROW_SIZE; i > 0; i--) {
+               data[i - 1] = i % UINT8_MAX;
+       }
+
+       data = isc_mem_reget(test_mctx, data, REGET_GROW_SIZE,
+                            REGET_SHRINK_SIZE);
+
+       for (size_t i = REGET_SHRINK_SIZE; i > 0; i--) {
+               assert_int_equal(data[i - 1], i % UINT8_MAX);
+       }
+
+       isc_mem_put(test_mctx, data, REGET_SHRINK_SIZE);
+}
+
 #if ISC_MEM_TRACKLINES
 
 /* test mem with no flags */
@@ -436,6 +470,8 @@ main(void) {
                                                _teardown),
                cmocka_unit_test_setup_teardown(isc_mem_inuse_test, _setup,
                                                _teardown),
+               cmocka_unit_test_setup_teardown(isc_mem_reget_test, _setup,
+                                               _teardown),
 
 #if !defined(__SANITIZE_THREAD__)
                cmocka_unit_test_setup_teardown(isc_mem_benchmark, _setup,