From 7e15dab94d3f008b0a6c296ad7afec9ed47ff1ac Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Wed, 29 Feb 2012 12:56:37 -0800 Subject: [PATCH] Add nallocm(). Add nallocm(), which computes the real allocation size that would result from the corresponding allocm() call. nallocm() is a functional superset of OS X's malloc_good_size(), in that it takes alignment constraints into account. --- doc/jemalloc.xml.in | 38 ++++++-- .../jemalloc/internal/jemalloc_internal.h.in | 4 - include/jemalloc/jemalloc.h.in | 1 + src/jemalloc.c | 22 +++++ test/allocm.c | 91 ++++++++++++++++--- 5 files changed, 131 insertions(+), 25 deletions(-) diff --git a/doc/jemalloc.xml.in b/doc/jemalloc.xml.in index e7cc6284..6aa412a1 100644 --- a/doc/jemalloc.xml.in +++ b/doc/jemalloc.xml.in @@ -41,6 +41,7 @@ rallocm sallocm dallocm + nallocm --> general purpose memory allocation functions @@ -154,6 +155,12 @@ void *ptr int flags + + int nallocm + size_t *rsize + size_t size + int flags + @@ -301,8 +308,9 @@ for (i = 0; i < nbins; i++) { The allocm, rallocm, - sallocm, and - dallocm functions all have a + sallocm, + dallocm, and + nallocm functions all have a flags argument that can be used to specify options. The functions only check the options that are contextually relevant. Use bitwise or (|) operations to @@ -351,7 +359,9 @@ for (i = 0; i < nbins; i++) { least size bytes of memory, sets *ptr to the base address of the allocation, and sets *rsize to the real size of the allocation if - rsize is not NULL. + rsize is not NULL. Behavior + is undefined if size is + 0. The rallocm function resizes the allocation at *ptr to be at least @@ -364,7 +374,8 @@ for (i = 0; i < nbins; i++) { language="C">size + extra) bytes, though inability to allocate the extra byte(s) will not by itself result in failure. Behavior is - undefined if (size + + undefined if size is 0, or if + (size + extra > SIZE_T_MAX). @@ -374,6 +385,15 @@ for (i = 0; i < nbins; i++) { The dallocm function causes the memory referenced by ptr to be made available for future allocations. + + The nallocm function allocates no + memory, but it performs the same size computation as the + allocm function, and if + rsize is not NULL it sets + *rsize to the real size of the allocation that + would result from the equivalent allocm + function call. Behavior is undefined if + size is 0. @@ -1857,11 +1877,13 @@ malloc_conf = "xmalloc:true";]]> Experimental API The allocm, rallocm, - sallocm, and - dallocm functions return + sallocm, + dallocm, and + nallocm functions return ALLOCM_SUCCESS on success; otherwise they return an - error value. The allocm and - rallocm functions will fail if: + error value. The allocm, + rallocm, and + nallocm functions will fail if: ALLOCM_ERR_OOM diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in index c21c218b..aa073467 100644 --- a/include/jemalloc/internal/jemalloc_internal.h.in +++ b/include/jemalloc/internal/jemalloc_internal.h.in @@ -548,10 +548,6 @@ sa2u(size_t size, size_t alignment, size_t *run_size_p) * 96 | 1100000 | 32 * 144 | 10100000 | 32 * 192 | 11000000 | 64 - * - * Depending on runtime settings, it is possible that arena_malloc() - * will further round up to a power of two, but that never causes - * correctness issues. */ usize = (size + (alignment - 1)) & (-alignment); /* diff --git a/include/jemalloc/jemalloc.h.in b/include/jemalloc/jemalloc.h.in index 580a5ec5..428c0d39 100644 --- a/include/jemalloc/jemalloc.h.in +++ b/include/jemalloc/jemalloc.h.in @@ -59,6 +59,7 @@ int JEMALLOC_P(rallocm)(void **ptr, size_t *rsize, size_t size, int JEMALLOC_P(sallocm)(const void *ptr, size_t *rsize, int flags) JEMALLOC_ATTR(nonnull(1)); int JEMALLOC_P(dallocm)(void *ptr, int flags) JEMALLOC_ATTR(nonnull(1)); +int JEMALLOC_P(nallocm)(size_t *rsize, size_t size, int flags); #ifdef __cplusplus }; diff --git a/src/jemalloc.c b/src/jemalloc.c index ccc3a209..34fd1aa0 100644 --- a/src/jemalloc.c +++ b/src/jemalloc.c @@ -1586,6 +1586,28 @@ JEMALLOC_P(dallocm)(void *ptr, int flags) return (ALLOCM_SUCCESS); } +JEMALLOC_ATTR(visibility("default")) +int +JEMALLOC_P(nallocm)(size_t *rsize, size_t size, int flags) +{ + size_t usize; + size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK) + & (SIZE_T_MAX-1)); + + assert(size != 0); + + if (malloc_init()) + return (ALLOCM_ERR_OOM); + + usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment, NULL); + if (usize == 0) + return (ALLOCM_ERR_OOM); + + if (rsize != NULL) + *rsize = usize; + return (ALLOCM_SUCCESS); +} + /* * End non-standard functions. */ diff --git a/test/allocm.c b/test/allocm.c index 59d0002e..762e350c 100644 --- a/test/allocm.c +++ b/test/allocm.c @@ -15,24 +15,33 @@ main(void) { int r; void *p; - size_t sz, alignment, total, tsz; + size_t nsz, rsz, sz, alignment, total; unsigned i; void *ps[NITER]; fprintf(stderr, "Test begin\n"); - sz = 0; - r = JEMALLOC_P(allocm)(&p, &sz, 42, 0); + sz = 42; + nsz = 0; + r = JEMALLOC_P(nallocm)(&nsz, sz, 0); + if (r != ALLOCM_SUCCESS) { + fprintf(stderr, "Unexpected nallocm() error\n"); + abort(); + } + rsz = 0; + r = JEMALLOC_P(allocm)(&p, &rsz, sz, 0); if (r != ALLOCM_SUCCESS) { fprintf(stderr, "Unexpected allocm() error\n"); abort(); } - if (sz < 42) + if (rsz < sz) fprintf(stderr, "Real size smaller than expected\n"); + if (nsz != rsz) + fprintf(stderr, "nallocm()/allocm() rsize mismatch\n"); if (JEMALLOC_P(dallocm)(p, 0) != ALLOCM_SUCCESS) fprintf(stderr, "Unexpected dallocm() error\n"); - r = JEMALLOC_P(allocm)(&p, NULL, 42, 0); + r = JEMALLOC_P(allocm)(&p, NULL, sz, 0); if (r != ALLOCM_SUCCESS) { fprintf(stderr, "Unexpected allocm() error\n"); abort(); @@ -40,11 +49,20 @@ main(void) if (JEMALLOC_P(dallocm)(p, 0) != ALLOCM_SUCCESS) fprintf(stderr, "Unexpected dallocm() error\n"); - r = JEMALLOC_P(allocm)(&p, NULL, 42, ALLOCM_ZERO); + nsz = 0; + r = JEMALLOC_P(nallocm)(&nsz, sz, ALLOCM_ZERO); + if (r != ALLOCM_SUCCESS) { + fprintf(stderr, "Unexpected nallocm() error\n"); + abort(); + } + rsz = 0; + r = JEMALLOC_P(allocm)(&p, &rsz, sz, ALLOCM_ZERO); if (r != ALLOCM_SUCCESS) { fprintf(stderr, "Unexpected allocm() error\n"); abort(); } + if (nsz != rsz) + fprintf(stderr, "nallocm()/allocm() rsize mismatch\n"); if (JEMALLOC_P(dallocm)(p, 0) != ALLOCM_SUCCESS) fprintf(stderr, "Unexpected dallocm() error\n"); @@ -55,12 +73,22 @@ main(void) alignment = 0x80000000LU; sz = 0x80000000LU; #endif - r = JEMALLOC_P(allocm)(&p, NULL, sz, ALLOCM_ALIGN(alignment)); + nsz = 0; + r = JEMALLOC_P(nallocm)(&nsz, sz, ALLOCM_ALIGN(alignment)); + if (r == ALLOCM_SUCCESS) { + fprintf(stderr, + "Expected error for nallocm(&nsz, %zu, 0x%x)\n", + sz, ALLOCM_ALIGN(alignment)); + } + rsz = 0; + r = JEMALLOC_P(allocm)(&p, &rsz, sz, ALLOCM_ALIGN(alignment)); if (r == ALLOCM_SUCCESS) { fprintf(stderr, "Expected error for allocm(&p, %zu, 0x%x)\n", sz, ALLOCM_ALIGN(alignment)); } + if (nsz != rsz) + fprintf(stderr, "nallocm()/allocm() rsize mismatch\n"); #if LG_SIZEOF_PTR == 3 alignment = 0x4000000000000000LLU; @@ -69,7 +97,12 @@ main(void) alignment = 0x40000000LU; sz = 0x84000001LU; #endif - r = JEMALLOC_P(allocm)(&p, NULL, sz, ALLOCM_ALIGN(alignment)); + nsz = 0; + r = JEMALLOC_P(nallocm)(&nsz, sz, ALLOCM_ALIGN(alignment)); + if (r != ALLOCM_SUCCESS) + fprintf(stderr, "Unexpected nallocm() error\n"); + rsz = 0; + r = JEMALLOC_P(allocm)(&p, &rsz, sz, ALLOCM_ALIGN(alignment)); if (r == ALLOCM_SUCCESS) { fprintf(stderr, "Expected error for allocm(&p, %zu, 0x%x)\n", @@ -82,12 +115,22 @@ main(void) #else sz = 0xfffffff0LU; #endif - r = JEMALLOC_P(allocm)(&p, NULL, sz, ALLOCM_ALIGN(alignment)); + nsz = 0; + r = JEMALLOC_P(nallocm)(&nsz, sz, ALLOCM_ALIGN(alignment)); + if (r == ALLOCM_SUCCESS) { + fprintf(stderr, + "Expected error for nallocm(&nsz, %zu, 0x%x)\n", + sz, ALLOCM_ALIGN(alignment)); + } + rsz = 0; + r = JEMALLOC_P(allocm)(&p, &rsz, sz, ALLOCM_ALIGN(alignment)); if (r == ALLOCM_SUCCESS) { fprintf(stderr, "Expected error for allocm(&p, %zu, 0x%x)\n", sz, ALLOCM_ALIGN(alignment)); } + if (nsz != rsz) + fprintf(stderr, "nallocm()/allocm() rsize mismatch\n"); for (i = 0; i < NITER; i++) ps[i] = NULL; @@ -101,21 +144,43 @@ main(void) sz < 3 * alignment && sz < (1U << 31); sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { for (i = 0; i < NITER; i++) { - r = JEMALLOC_P(allocm)(&ps[i], NULL, sz, + nsz = 0; + r = JEMALLOC_P(nallocm)(&nsz, sz, ALLOCM_ALIGN(alignment) | ALLOCM_ZERO); if (r != ALLOCM_SUCCESS) { fprintf(stderr, - "Error for size %zu (0x%zx): %d\n", + "nallocm() error for size %zu" + " (0x%zx): %d\n", sz, sz, r); exit(1); } + rsz = 0; + r = JEMALLOC_P(allocm)(&ps[i], &rsz, sz, + ALLOCM_ALIGN(alignment) | ALLOCM_ZERO); + if (r != ALLOCM_SUCCESS) { + fprintf(stderr, + "allocm() error for size %zu" + " (0x%zx): %d\n", + sz, sz, r); + exit(1); + } + if (rsz < sz) { + fprintf(stderr, + "Real size smaller than" + " expected\n"); + } + if (nsz != rsz) { + fprintf(stderr, + "nallocm()/allocm() rsize" + " mismatch\n"); + } if ((uintptr_t)p & (alignment-1)) { fprintf(stderr, "%p inadequately aligned for" " alignment: %zu\n", p, alignment); } - JEMALLOC_P(sallocm)(ps[i], &tsz, 0); - total += tsz; + JEMALLOC_P(sallocm)(ps[i], &rsz, 0); + total += rsz; if (total >= (MAXALIGN << 1)) break; }