#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)
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);
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] \
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;
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);
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 */
_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,