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.
This commit is contained in:
Jason Evans 2012-02-29 12:56:37 -08:00
parent 4bb0983013
commit 7e15dab94d
5 changed files with 131 additions and 25 deletions

View File

@ -41,6 +41,7 @@
<refname>rallocm</refname> <refname>rallocm</refname>
<refname>sallocm</refname> <refname>sallocm</refname>
<refname>dallocm</refname> <refname>dallocm</refname>
<refname>nallocm</refname>
--> -->
<refpurpose>general purpose memory allocation functions</refpurpose> <refpurpose>general purpose memory allocation functions</refpurpose>
</refnamediv> </refnamediv>
@ -154,6 +155,12 @@
<paramdef>void *<parameter>ptr</parameter></paramdef> <paramdef>void *<parameter>ptr</parameter></paramdef>
<paramdef>int <parameter>flags</parameter></paramdef> <paramdef>int <parameter>flags</parameter></paramdef>
</funcprototype> </funcprototype>
<funcprototype>
<funcdef>int <function>nallocm</function></funcdef>
<paramdef>size_t *<parameter>rsize</parameter></paramdef>
<paramdef>size_t <parameter>size</parameter></paramdef>
<paramdef>int <parameter>flags</parameter></paramdef>
</funcprototype>
</refsect2> </refsect2>
</funcsynopsis> </funcsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -301,8 +308,9 @@ for (i = 0; i < nbins; i++) {
<para>The <function>allocm<parameter/></function>, <para>The <function>allocm<parameter/></function>,
<function>rallocm<parameter/></function>, <function>rallocm<parameter/></function>,
<function>sallocm<parameter/></function>, and <function>sallocm<parameter/></function>,
<function>dallocm<parameter/></function> functions all have a <function>dallocm<parameter/></function>, and
<function>nallocm<parameter/></function> functions all have a
<parameter>flags</parameter> argument that can be used to specify <parameter>flags</parameter> argument that can be used to specify
options. The functions only check the options that are contextually options. The functions only check the options that are contextually
relevant. Use bitwise or (<code language="C">|</code>) operations to relevant. Use bitwise or (<code language="C">|</code>) operations to
@ -351,7 +359,9 @@ for (i = 0; i < nbins; i++) {
least <parameter>size</parameter> bytes of memory, sets least <parameter>size</parameter> bytes of memory, sets
<parameter>*ptr</parameter> to the base address of the allocation, and <parameter>*ptr</parameter> to the base address of the allocation, and
sets <parameter>*rsize</parameter> to the real size of the allocation if sets <parameter>*rsize</parameter> to the real size of the allocation if
<parameter>rsize</parameter> is not <constant>NULL</constant>.</para> <parameter>rsize</parameter> is not <constant>NULL</constant>. Behavior
is undefined if <parameter>size</parameter> is
<constant>0<constant>.</para>
<para>The <function>rallocm<parameter/></function> function resizes the <para>The <function>rallocm<parameter/></function> function resizes the
allocation at <parameter>*ptr</parameter> to be at least allocation at <parameter>*ptr</parameter> to be at least
@ -364,7 +374,8 @@ for (i = 0; i < nbins; i++) {
language="C"><parameter>size</parameter> + language="C"><parameter>size</parameter> +
<parameter>extra</parameter>)</code> bytes, though inability to allocate <parameter>extra</parameter>)</code> bytes, though inability to allocate
the extra byte(s) will not by itself result in failure. Behavior is the extra byte(s) will not by itself result in failure. Behavior is
undefined if <code language="C">(<parameter>size</parameter> + undefined if <parameter>size</parameter> is <constant>0<constant>, or if
<code language="C">(<parameter>size</parameter> +
<parameter>extra</parameter> &gt; <parameter>extra</parameter> &gt;
<constant>SIZE_T_MAX</constant>)</code>.</para> <constant>SIZE_T_MAX</constant>)</code>.</para>
@ -374,6 +385,15 @@ for (i = 0; i < nbins; i++) {
<para>The <function>dallocm<parameter/></function> function causes the <para>The <function>dallocm<parameter/></function> function causes the
memory referenced by <parameter>ptr</parameter> to be made available for memory referenced by <parameter>ptr</parameter> to be made available for
future allocations.</para> future allocations.</para>
<para>The <function>nallocm<parameter/></function> function allocates no
memory, but it performs the same size computation as the
<function>allocm<parameter/></function> function, and if
<parameter>rsize</parameter> is not <constant>NULL</constant> it sets
<parameter>*rsize</parameter> to the real size of the allocation that
would result from the equivalent <function>allocm<parameter/></function>
function call. Behavior is undefined if
<parameter>size</parameter> is <constant>0<constant>.</para>
</refsect2> </refsect2>
</refsect1> </refsect1>
<refsect1 id="tuning"> <refsect1 id="tuning">
@ -1857,11 +1877,13 @@ malloc_conf = "xmalloc:true";]]></programlisting>
<title>Experimental API</title> <title>Experimental API</title>
<para>The <function>allocm<parameter/></function>, <para>The <function>allocm<parameter/></function>,
<function>rallocm<parameter/></function>, <function>rallocm<parameter/></function>,
<function>sallocm<parameter/></function>, and <function>sallocm<parameter/></function>,
<function>dallocm<parameter/></function> functions return <function>dallocm<parameter/></function>, and
<function>nallocm<parameter/></function> functions return
<constant>ALLOCM_SUCCESS</constant> on success; otherwise they return an <constant>ALLOCM_SUCCESS</constant> on success; otherwise they return an
error value. The <function>allocm<parameter/></function> and error value. The <function>allocm<parameter/></function>,
<function>rallocm<parameter/></function> functions will fail if: <function>rallocm<parameter/></function>, and
<function>nallocm<parameter/></function> functions will fail if:
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><errorname>ALLOCM_ERR_OOM</errorname></term> <term><errorname>ALLOCM_ERR_OOM</errorname></term>

View File

@ -548,10 +548,6 @@ sa2u(size_t size, size_t alignment, size_t *run_size_p)
* 96 | 1100000 | 32 * 96 | 1100000 | 32
* 144 | 10100000 | 32 * 144 | 10100000 | 32
* 192 | 11000000 | 64 * 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); usize = (size + (alignment - 1)) & (-alignment);
/* /*

View File

@ -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) int JEMALLOC_P(sallocm)(const void *ptr, size_t *rsize, int flags)
JEMALLOC_ATTR(nonnull(1)); JEMALLOC_ATTR(nonnull(1));
int JEMALLOC_P(dallocm)(void *ptr, 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 #ifdef __cplusplus
}; };

View File

@ -1586,6 +1586,28 @@ JEMALLOC_P(dallocm)(void *ptr, int flags)
return (ALLOCM_SUCCESS); 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. * End non-standard functions.
*/ */

View File

@ -15,24 +15,33 @@ main(void)
{ {
int r; int r;
void *p; void *p;
size_t sz, alignment, total, tsz; size_t nsz, rsz, sz, alignment, total;
unsigned i; unsigned i;
void *ps[NITER]; void *ps[NITER];
fprintf(stderr, "Test begin\n"); fprintf(stderr, "Test begin\n");
sz = 0; sz = 42;
r = JEMALLOC_P(allocm)(&p, &sz, 42, 0); 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) { if (r != ALLOCM_SUCCESS) {
fprintf(stderr, "Unexpected allocm() error\n"); fprintf(stderr, "Unexpected allocm() error\n");
abort(); abort();
} }
if (sz < 42) if (rsz < sz)
fprintf(stderr, "Real size smaller than expected\n"); 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) if (JEMALLOC_P(dallocm)(p, 0) != ALLOCM_SUCCESS)
fprintf(stderr, "Unexpected dallocm() error\n"); 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) { if (r != ALLOCM_SUCCESS) {
fprintf(stderr, "Unexpected allocm() error\n"); fprintf(stderr, "Unexpected allocm() error\n");
abort(); abort();
@ -40,11 +49,20 @@ main(void)
if (JEMALLOC_P(dallocm)(p, 0) != ALLOCM_SUCCESS) if (JEMALLOC_P(dallocm)(p, 0) != ALLOCM_SUCCESS)
fprintf(stderr, "Unexpected dallocm() error\n"); 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) { if (r != ALLOCM_SUCCESS) {
fprintf(stderr, "Unexpected allocm() error\n"); fprintf(stderr, "Unexpected allocm() error\n");
abort(); abort();
} }
if (nsz != rsz)
fprintf(stderr, "nallocm()/allocm() rsize mismatch\n");
if (JEMALLOC_P(dallocm)(p, 0) != ALLOCM_SUCCESS) if (JEMALLOC_P(dallocm)(p, 0) != ALLOCM_SUCCESS)
fprintf(stderr, "Unexpected dallocm() error\n"); fprintf(stderr, "Unexpected dallocm() error\n");
@ -55,12 +73,22 @@ main(void)
alignment = 0x80000000LU; alignment = 0x80000000LU;
sz = 0x80000000LU; sz = 0x80000000LU;
#endif #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) { if (r == ALLOCM_SUCCESS) {
fprintf(stderr, fprintf(stderr,
"Expected error for allocm(&p, %zu, 0x%x)\n", "Expected error for allocm(&p, %zu, 0x%x)\n",
sz, ALLOCM_ALIGN(alignment)); sz, ALLOCM_ALIGN(alignment));
} }
if (nsz != rsz)
fprintf(stderr, "nallocm()/allocm() rsize mismatch\n");
#if LG_SIZEOF_PTR == 3 #if LG_SIZEOF_PTR == 3
alignment = 0x4000000000000000LLU; alignment = 0x4000000000000000LLU;
@ -69,7 +97,12 @@ main(void)
alignment = 0x40000000LU; alignment = 0x40000000LU;
sz = 0x84000001LU; sz = 0x84000001LU;
#endif #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) { if (r == ALLOCM_SUCCESS) {
fprintf(stderr, fprintf(stderr,
"Expected error for allocm(&p, %zu, 0x%x)\n", "Expected error for allocm(&p, %zu, 0x%x)\n",
@ -82,12 +115,22 @@ main(void)
#else #else
sz = 0xfffffff0LU; sz = 0xfffffff0LU;
#endif #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) { if (r == ALLOCM_SUCCESS) {
fprintf(stderr, fprintf(stderr,
"Expected error for allocm(&p, %zu, 0x%x)\n", "Expected error for allocm(&p, %zu, 0x%x)\n",
sz, ALLOCM_ALIGN(alignment)); sz, ALLOCM_ALIGN(alignment));
} }
if (nsz != rsz)
fprintf(stderr, "nallocm()/allocm() rsize mismatch\n");
for (i = 0; i < NITER; i++) for (i = 0; i < NITER; i++)
ps[i] = NULL; ps[i] = NULL;
@ -101,21 +144,43 @@ main(void)
sz < 3 * alignment && sz < (1U << 31); sz < 3 * alignment && sz < (1U << 31);
sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
for (i = 0; i < NITER; i++) { 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); ALLOCM_ALIGN(alignment) | ALLOCM_ZERO);
if (r != ALLOCM_SUCCESS) { if (r != ALLOCM_SUCCESS) {
fprintf(stderr, fprintf(stderr,
"Error for size %zu (0x%zx): %d\n", "nallocm() error for size %zu"
" (0x%zx): %d\n",
sz, sz, r); sz, sz, r);
exit(1); 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)) { if ((uintptr_t)p & (alignment-1)) {
fprintf(stderr, fprintf(stderr,
"%p inadequately aligned for" "%p inadequately aligned for"
" alignment: %zu\n", p, alignment); " alignment: %zu\n", p, alignment);
} }
JEMALLOC_P(sallocm)(ps[i], &tsz, 0); JEMALLOC_P(sallocm)(ps[i], &rsz, 0);
total += tsz; total += rsz;
if (total >= (MAXALIGN << 1)) if (total >= (MAXALIGN << 1))
break; break;
} }