From 822247564ce9e1bc04824bc4a0fa1f5c942e2a83 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Wed, 27 Sep 2023 19:33:44 +0300 Subject: [PATCH] allocator fun continues Signed-off-by: Pantelis Antoniou --- src/internal/fy-allocators.c | 85 +++++++++++++++++++++++++++------- src/util/fy-allocator-dedup.c | 34 +++++++++++++- src/util/fy-allocator-mremap.c | 33 +++++++++---- 3 files changed, 123 insertions(+), 29 deletions(-) diff --git a/src/internal/fy-allocators.c b/src/internal/fy-allocators.c index 00c4998..9ba26f7 100644 --- a/src/internal/fy-allocators.c +++ b/src/internal/fy-allocators.c @@ -73,15 +73,18 @@ static void dump_allocator_info(struct fy_allocator *a, fy_alloc_tag tag) free(info); } -static int allocator_test(const char *allocator, size_t size) +static int allocator_test(const char *allocator, const char *parent_allocator, size_t size) { struct fy_linear_setup_data lsetupdata; - const void *gsetupdata = NULL; - struct fy_allocator *a; + struct fy_dedup_setup_data dsetupdata; + const void *gsetupdata = NULL, *psetupdata = NULL; + struct fy_allocator *a = NULL, *pa = NULL; fy_alloc_tag tag0; char *names; - bool is_linear; + bool is_linear, is_dedup; unsigned int *uintp[16]; + uint8_t *p; + size_t psz = 4096; unsigned int i; names = fy_allocator_get_names(); @@ -90,11 +93,28 @@ static int allocator_test(const char *allocator, size_t size) free(names); is_linear = !strcmp(allocator, "linear"); + is_dedup = !strcmp(allocator, "dedup"); if (is_linear) { - memset(&lsetupdata, 0, sizeof(lsetupdata)); - lsetupdata.size = size ? size : 4096; gsetupdata = &lsetupdata; + } else if (is_dedup) { + + fprintf(stderr, "Using parent-allocator: %s\n", parent_allocator); + + if (!strcmp(parent_allocator, "linear")) { + memset(&lsetupdata, 0, sizeof(lsetupdata)); + lsetupdata.size = size ? size : 4096; + + psetupdata = &lsetupdata; + } else + psetupdata = NULL; + + pa = fy_allocator_create(parent_allocator, psetupdata); + assert(pa); + + memset(&dsetupdata, 0, sizeof(dsetupdata)); + dsetupdata.parent_allocator = pa; + gsetupdata = &dsetupdata; } else gsetupdata = NULL; @@ -121,11 +141,33 @@ static int allocator_test(const char *allocator, size_t size) for (i = 0; i < ARRAY_SIZE(uintp); i++) *uintp[i] = i; - /* assert */ + fprintf(stderr, "Dumping allocator areas before trim\n"); + dump_allocator_info(a, tag0); + + fy_allocator_trim_tag(a, tag0); + + fprintf(stderr, "Dumping allocator areas after trim\n"); + dump_allocator_info(a, tag0); + + fprintf(stderr, "Allocating %zu bytes\n", psz); + p = fy_allocator_alloc(a, tag0, psz, 1); + if (!p) { + fprintf(stderr, "failed to allocate %zu bytes\n", psz); + } else { + for (i = 0; i < psz; i++) + p[i] = i % 251; + } + + /* verify */ + if (p) { + for (i = 0; i < psz; i++) + assert(p[i] == (i % 251)); + } + for (i = 0; i < ARRAY_SIZE(uintp); i++) assert(*uintp[i] == i); - fprintf(stderr, "Dumping allocator areas before release\n"); + fprintf(stderr, "Dumping allocator areas after alloc\n"); dump_allocator_info(a, tag0); fprintf(stderr, "Releasing tag0\n"); @@ -134,16 +176,19 @@ static int allocator_test(const char *allocator, size_t size) fprintf(stderr, "Dumping allocator areas after release\n"); dump_allocator_info(a, FY_ALLOC_TAG_NONE); - fy_allocator_destroy(a); + if (a) + fy_allocator_destroy(a); + + if (pa) + fy_allocator_destroy(pa); - if (is_linear) - free(lsetupdata.buf); return 0; } static struct option lopts[] = { {"allocator", required_argument, 0, 'a' }, + {"parent", required_argument, 0, 'p' }, {"size", required_argument, 0, 's' }, {"help", no_argument, 0, 'h' }, {0, 0, 0, 0 }, @@ -163,9 +208,10 @@ static void display_usage(FILE *fp, const char *progname) fprintf(fp, "Usage:\n\t%s [options]\n", progname); fprintf(fp, "\noptions:\n"); - fprintf(fp, "\t--allocator , -a : Use allocator, one of: %s\n", names); - fprintf(fp, "\t--size , -s : Size for allocators that require one\n"); - fprintf(fp, "\t--help, -h : Display help message\n"); + fprintf(fp, "\t--allocator , -a : Use allocator, one of: %s\n", names); + fprintf(fp, "\t--parent , -p : Use parent allocator, one of: %s\n", names); + fprintf(fp, "\t--size , -s : Size for allocators that require one\n"); + fprintf(fp, "\t--help, -h : Display help message\n"); fprintf(fp, "\n"); free(names); @@ -176,16 +222,21 @@ int main(int argc, char *argv[]) int opt, lidx, rc; int exitcode = EXIT_FAILURE; const char *allocator = "linear"; + const char *parent_allocator = "linear"; size_t size = 0; - while ((opt = getopt_long_only(argc, argv, "a:s:h", lopts, &lidx)) != -1) { + while ((opt = getopt_long_only(argc, argv, "a:p:s:h", lopts, &lidx)) != -1) { switch (opt) { case 'a': + case 'p': if (!fy_allocator_is_available(optarg)) { fprintf(stderr, "Error: illegal allocator name \"%s\"\n", optarg); goto err_out_usage; } - allocator = optarg; + if (opt == 'a') + allocator = optarg; + else + parent_allocator = optarg; break; case 's': size = (size_t)atoi(optarg); @@ -198,7 +249,7 @@ int main(int argc, char *argv[]) } } - rc = allocator_test(allocator, size); + rc = allocator_test(allocator, parent_allocator, size); if (rc) { fprintf(stderr, "Error: allocator_test() failed\n"); goto err_out; diff --git a/src/util/fy-allocator-dedup.c b/src/util/fy-allocator-dedup.c index 87dc501..63d03e8 100644 --- a/src/util/fy-allocator-dedup.c +++ b/src/util/fy-allocator-dedup.c @@ -385,7 +385,7 @@ static int fy_dedup_tag_update_stats(struct fy_dedup_allocator *da, struct fy_de fy_allocator_update_stats(da->entries_allocator, dt->entries_tag, stats); fy_allocator_update_stats(da->parent_allocator, dt->content_tag, stats); - /* and update with this ones */ + /* and update with these ones */ for (i = 0; i < ARRAY_SIZE(dt->stats.counters); i++) { stats->counters[i] += dt->stats.counters[i]; dt->stats.counters[i] = 0; @@ -992,7 +992,37 @@ static void fy_dedup_reset_tag(struct fy_allocator *a, fy_alloc_tag tag) static struct fy_allocator_info * fy_dedup_get_info(struct fy_allocator *a, fy_alloc_tag tag) { - return NULL; + struct fy_dedup_allocator *da; + struct fy_dedup_tag *dt; + struct fy_allocator_info *info; + struct fy_allocator_tag_info *tag_info; + unsigned int i; + + if (!a) + return NULL; + + /* full dump not supported yet */ + if (tag == FY_ALLOC_TAG_NONE) + return NULL; + + da = container_of(a, struct fy_dedup_allocator, a); + + dt = fy_dedup_tag_from_tag(da, tag); + if (!dt) + return NULL; + + info = fy_allocator_get_info(da->parent_allocator, dt->content_tag); + if (!info) + return NULL; + + /* we will have to change the tag from content to this one */ + for (i = 0; i < info->num_tag_infos; i++) { + tag_info = &info->tag_infos[i]; + if (tag_info->tag == dt->content_tag) + tag_info->tag = tag; + } + + return info; } static const void *fy_dedup_get_single_area(struct fy_allocator *a, fy_alloc_tag tag, size_t *sizep, size_t *startp, size_t *allocp) diff --git a/src/util/fy-allocator-mremap.c b/src/util/fy-allocator-mremap.c index 890d555..a2d7131 100644 --- a/src/util/fy-allocator-mremap.c +++ b/src/util/fy-allocator-mremap.c @@ -65,11 +65,17 @@ fy_mremap_arena_create(struct fy_mremap_allocator *mra, struct fy_mremap_tag *mr } else { #if USE_MREMAP mran = mremap(mem, balloon_size, size_page_align, 0); - assert(mran == MAP_FAILED || mran == mem); + /* either it fails, or it moves we handle it */ #else /* we don't shrink, we just unmap over the limit */ rc = munmap(mem + size_page_align, balloon_size - size_page_align); - assert(!rc); + if (rc) { +#ifdef DEBUG_ARENA + fprintf(stderr, "%s: failed to unmap for shink\n", __func__); +#endif + size_page_align = balloon_size; /* keep the balloon size? */ + } + mran = mem; #endif } if (mran == MAP_FAILED) @@ -185,14 +191,15 @@ static int fy_mremap_arena_trim(struct fy_mremap_allocator *mra, struct fy_mrema #endif #if USE_MREMAP - /* failure to shrink a mapping is unthinkable */ + /* failure to shrink a mapping is unthinkable, but check anyway */ mem = mremap(mran, mran->size, new_size, 0); - assert(mem != MAP_FAILED); - assert(mem == mran); + if (mem == MAP_FAILED || mem != mran) + return -1; #else /* we don't shrink, we just unmap over the limit */ - rc = munmap((void *)mra + new_size, mran->size - new_size); - assert(!rc); + rc = munmap((void *)mran + new_size, mran->size - new_size); + if (rc) + return -1; #endif mran->size = new_size; return 0; @@ -340,7 +347,9 @@ static void *fy_mremap_tag_alloc(struct fy_mremap_allocator *mra, struct fy_mrem if (!mran) goto err_out; - // fprintf(stderr, "allocated new big mran->size=%zu size=%zu\n", mran->size, size); +#ifdef DEBUG_ARENA + fprintf(stderr, "allocated new big mran->size=%zu size=%zu\n", mran->size, size); +#endif fy_mremap_arena_list_add_tail(&mrt->arenas, mran); goto do_alloc; @@ -369,7 +378,9 @@ static void *fy_mremap_tag_alloc(struct fy_mremap_allocator *mra, struct fy_mrem if (rc) continue; - // fprintf(stderr, "grow successful mran->size=%zu size=%zu\n", mran->size, size); +#ifdef DEBUG_ARENA + fprintf(stderr, "grow successful mran->size=%zu size=%zu\n", mran->size, size); +#endif left = mran->size - fy_size_t_align(mran->next, align); assert(left >= size); @@ -397,7 +408,9 @@ static void *fy_mremap_tag_alloc(struct fy_mremap_allocator *mra, struct fy_mrem mrt->next_arena_sz = (size_t)(mrt->next_arena_sz * mra->grow_ratio); - // fprintf(stderr, "allocated new %p mran->size=%zu size=%zu\n", mran, mran->size, size); +#ifdef DEBUG_ARENA + fprintf(stderr, "allocated new %p mran->size=%zu size=%zu\n", mran, mran->size, size); +#endif fy_mremap_arena_list_add(&mrt->arenas, mran);