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>sallocm</refname>
<refname>dallocm</refname>
<refname>nallocm</refname>
-->
<refpurpose>general purpose memory allocation functions</refpurpose>
</refnamediv>
@ -154,6 +155,12 @@
<paramdef>void *<parameter>ptr</parameter></paramdef>
<paramdef>int <parameter>flags</parameter></paramdef>
</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>
</funcsynopsis>
</refsynopsisdiv>
@ -301,8 +308,9 @@ for (i = 0; i < nbins; i++) {
<para>The <function>allocm<parameter/></function>,
<function>rallocm<parameter/></function>,
<function>sallocm<parameter/></function>, and
<function>dallocm<parameter/></function> functions all have a
<function>sallocm<parameter/></function>,
<function>dallocm<parameter/></function>, and
<function>nallocm<parameter/></function> functions all have a
<parameter>flags</parameter> argument that can be used to specify
options. The functions only check the options that are contextually
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
<parameter>*ptr</parameter> to the base address of the allocation, and
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
allocation at <parameter>*ptr</parameter> to be at least
@ -364,7 +374,8 @@ for (i = 0; i < nbins; i++) {
language="C"><parameter>size</parameter> +
<parameter>extra</parameter>)</code> bytes, though inability to allocate
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;
<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
memory referenced by <parameter>ptr</parameter> to be made available for
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>
</refsect1>
<refsect1 id="tuning">
@ -1857,11 +1877,13 @@ malloc_conf = "xmalloc:true";]]></programlisting>
<title>Experimental API</title>
<para>The <function>allocm<parameter/></function>,
<function>rallocm<parameter/></function>,
<function>sallocm<parameter/></function>, and
<function>dallocm<parameter/></function> functions return
<function>sallocm<parameter/></function>,
<function>dallocm<parameter/></function>, and
<function>nallocm<parameter/></function> functions return
<constant>ALLOCM_SUCCESS</constant> on success; otherwise they return an
error value. The <function>allocm<parameter/></function> and
<function>rallocm<parameter/></function> functions will fail if:
error value. The <function>allocm<parameter/></function>,
<function>rallocm<parameter/></function>, and
<function>nallocm<parameter/></function> functions will fail if:
<variablelist>
<varlistentry>
<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
* 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);
/*

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)
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
};

View File

@ -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.
*/

View File

@ -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;
}