Implement the *allocx() API.
Implement the *allocx() API, which is a successor to the *allocm() API. The *allocx() functions are slightly simpler to use because they have fewer parameters, they directly return the results of primary interest, and mallocx()/rallocx() avoid the strict aliasing pitfall that allocm()/rallocx() share with posix_memalign(). The following code violates strict aliasing rules: foo_t *foo; allocm((void **)&foo, NULL, 42, 0); whereas the following is safe: foo_t *foo; void *p; allocm(&p, NULL, 42, 0); foo = (foo_t *)p; mallocx() does not have this problem: foo_t *foo = (foo_t *)mallocx(42, 0);
This commit is contained in:
parent
0ac396a06a
commit
d82a5e6a34
@ -112,13 +112,16 @@ TESTS_UNIT := $(srcroot)test/unit/bitmap.c $(srcroot)test/unit/math.c \
|
|||||||
$(srcroot)test/unit/SFMT.c $(srcroot)test/unit/tsd.c
|
$(srcroot)test/unit/SFMT.c $(srcroot)test/unit/tsd.c
|
||||||
TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \
|
TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \
|
||||||
$(srcroot)test/integration/allocated.c \
|
$(srcroot)test/integration/allocated.c \
|
||||||
$(srcroot)test/integration/ALLOCM_ARENA.c \
|
$(srcroot)test/integration/mallocx.c \
|
||||||
$(srcroot)test/integration/mremap.c \
|
$(srcroot)test/integration/mremap.c \
|
||||||
$(srcroot)test/integration/posix_memalign.c \
|
$(srcroot)test/integration/posix_memalign.c \
|
||||||
|
$(srcroot)test/integration/rallocx.c \
|
||||||
$(srcroot)test/integration/thread_arena.c \
|
$(srcroot)test/integration/thread_arena.c \
|
||||||
$(srcroot)test/integration/thread_tcache_enabled.c
|
$(srcroot)test/integration/thread_tcache_enabled.c \
|
||||||
|
$(srcroot)test/integration/xallocx.c
|
||||||
ifeq ($(enable_experimental), 1)
|
ifeq ($(enable_experimental), 1)
|
||||||
TESTS_INTEGRATION += $(srcroot)test/integration/allocm.c \
|
TESTS_INTEGRATION += $(srcroot)test/integration/allocm.c \
|
||||||
|
$(srcroot)test/integration/ALLOCM_ARENA.c \
|
||||||
$(srcroot)test/integration/rallocm.c
|
$(srcroot)test/integration/rallocm.c
|
||||||
endif
|
endif
|
||||||
TESTS_STRESS :=
|
TESTS_STRESS :=
|
||||||
|
@ -417,7 +417,7 @@ AC_PROG_RANLIB
|
|||||||
AC_PATH_PROG([LD], [ld], [false], [$PATH])
|
AC_PATH_PROG([LD], [ld], [false], [$PATH])
|
||||||
AC_PATH_PROG([AUTOCONF], [autoconf], [false], [$PATH])
|
AC_PATH_PROG([AUTOCONF], [autoconf], [false], [$PATH])
|
||||||
|
|
||||||
public_syms="malloc_conf malloc_message malloc calloc posix_memalign aligned_alloc realloc free malloc_usable_size malloc_stats_print mallctl mallctlnametomib mallctlbymib"
|
public_syms="malloc_conf malloc_message malloc calloc posix_memalign aligned_alloc realloc free mallocx rallocx xallocx sallocx dallocx nallocx mallctl mallctlnametomib mallctlbymib malloc_stats_print malloc_usable_size"
|
||||||
|
|
||||||
dnl Check for allocator-related functions that should be wrapped.
|
dnl Check for allocator-related functions that should be wrapped.
|
||||||
AC_CHECK_FUNC([memalign],
|
AC_CHECK_FUNC([memalign],
|
||||||
|
@ -33,11 +33,17 @@
|
|||||||
<refname>aligned_alloc</refname>
|
<refname>aligned_alloc</refname>
|
||||||
<refname>realloc</refname>
|
<refname>realloc</refname>
|
||||||
<refname>free</refname>
|
<refname>free</refname>
|
||||||
<refname>malloc_usable_size</refname>
|
<refname>mallocx</refname>
|
||||||
<refname>malloc_stats_print</refname>
|
<refname>rallocx</refname>
|
||||||
|
<refname>xallocx</refname>
|
||||||
|
<refname>sallocx</refname>
|
||||||
|
<refname>dallocx</refname>
|
||||||
|
<refname>nallocx</refname>
|
||||||
<refname>mallctl</refname>
|
<refname>mallctl</refname>
|
||||||
<refname>mallctlnametomib</refname>
|
<refname>mallctlnametomib</refname>
|
||||||
<refname>mallctlbymib</refname>
|
<refname>mallctlbymib</refname>
|
||||||
|
<refname>malloc_stats_print</refname>
|
||||||
|
<refname>malloc_usable_size</refname>
|
||||||
<refname>allocm</refname>
|
<refname>allocm</refname>
|
||||||
<refname>rallocm</refname>
|
<refname>rallocm</refname>
|
||||||
<refname>sallocm</refname>
|
<refname>sallocm</refname>
|
||||||
@ -92,16 +98,37 @@
|
|||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Non-standard API</title>
|
<title>Non-standard API</title>
|
||||||
<funcprototype>
|
<funcprototype>
|
||||||
<funcdef>size_t <function>malloc_usable_size</function></funcdef>
|
<funcdef>void *<function>mallocx</function></funcdef>
|
||||||
<paramdef>const void *<parameter>ptr</parameter></paramdef>
|
<paramdef>size_t <parameter>size</parameter></paramdef>
|
||||||
|
<paramdef>int <parameter>flags</parameter></paramdef>
|
||||||
</funcprototype>
|
</funcprototype>
|
||||||
<funcprototype>
|
<funcprototype>
|
||||||
<funcdef>void <function>malloc_stats_print</function></funcdef>
|
<funcdef>void *<function>rallocx</function></funcdef>
|
||||||
<paramdef>void <parameter>(*write_cb)</parameter>
|
<paramdef>void *<parameter>ptr</parameter></paramdef>
|
||||||
<funcparams>void *, const char *</funcparams>
|
<paramdef>size_t <parameter>size</parameter></paramdef>
|
||||||
</paramdef>
|
<paramdef>int <parameter>flags</parameter></paramdef>
|
||||||
<paramdef>void *<parameter>cbopaque</parameter></paramdef>
|
</funcprototype>
|
||||||
<paramdef>const char *<parameter>opts</parameter></paramdef>
|
<funcprototype>
|
||||||
|
<funcdef>size_t <function>xallocx</function></funcdef>
|
||||||
|
<paramdef>void *<parameter>ptr</parameter></paramdef>
|
||||||
|
<paramdef>size_t <parameter>size</parameter></paramdef>
|
||||||
|
<paramdef>size_t <parameter>extra</parameter></paramdef>
|
||||||
|
<paramdef>int <parameter>flags</parameter></paramdef>
|
||||||
|
</funcprototype>
|
||||||
|
<funcprototype>
|
||||||
|
<funcdef>size_t <function>sallocx</function></funcdef>
|
||||||
|
<paramdef>void *<parameter>ptr</parameter></paramdef>
|
||||||
|
<paramdef>int <parameter>flags</parameter></paramdef>
|
||||||
|
</funcprototype>
|
||||||
|
<funcprototype>
|
||||||
|
<funcdef>void <function>dallocx</function></funcdef>
|
||||||
|
<paramdef>void *<parameter>ptr</parameter></paramdef>
|
||||||
|
<paramdef>int <parameter>flags</parameter></paramdef>
|
||||||
|
</funcprototype>
|
||||||
|
<funcprototype>
|
||||||
|
<funcdef>size_t <function>nallocx</function></funcdef>
|
||||||
|
<paramdef>size_t <parameter>size</parameter></paramdef>
|
||||||
|
<paramdef>int <parameter>flags</parameter></paramdef>
|
||||||
</funcprototype>
|
</funcprototype>
|
||||||
<funcprototype>
|
<funcprototype>
|
||||||
<funcdef>int <function>mallctl</function></funcdef>
|
<funcdef>int <function>mallctl</function></funcdef>
|
||||||
@ -126,6 +153,18 @@
|
|||||||
<paramdef>void *<parameter>newp</parameter></paramdef>
|
<paramdef>void *<parameter>newp</parameter></paramdef>
|
||||||
<paramdef>size_t <parameter>newlen</parameter></paramdef>
|
<paramdef>size_t <parameter>newlen</parameter></paramdef>
|
||||||
</funcprototype>
|
</funcprototype>
|
||||||
|
<funcprototype>
|
||||||
|
<funcdef>void <function>malloc_stats_print</function></funcdef>
|
||||||
|
<paramdef>void <parameter>(*write_cb)</parameter>
|
||||||
|
<funcparams>void *, const char *</funcparams>
|
||||||
|
</paramdef>
|
||||||
|
<paramdef>void *<parameter>cbopaque</parameter></paramdef>
|
||||||
|
<paramdef>const char *<parameter>opts</parameter></paramdef>
|
||||||
|
</funcprototype>
|
||||||
|
<funcprototype>
|
||||||
|
<funcdef>size_t <function>malloc_usable_size</function></funcdef>
|
||||||
|
<paramdef>const void *<parameter>ptr</parameter></paramdef>
|
||||||
|
</funcprototype>
|
||||||
<funcprototype>
|
<funcprototype>
|
||||||
<funcdef>void <function>(*malloc_message)</function></funcdef>
|
<funcdef>void <function>(*malloc_message)</function></funcdef>
|
||||||
<paramdef>void *<parameter>cbopaque</parameter></paramdef>
|
<paramdef>void *<parameter>cbopaque</parameter></paramdef>
|
||||||
@ -225,41 +264,99 @@
|
|||||||
</refsect2>
|
</refsect2>
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Non-standard API</title>
|
<title>Non-standard API</title>
|
||||||
|
<para>The <function>mallocx<parameter/></function>,
|
||||||
|
<function>rallocx<parameter/></function>,
|
||||||
|
<function>xallocx<parameter/></function>,
|
||||||
|
<function>sallocx<parameter/></function>,
|
||||||
|
<function>dallocx<parameter/></function>, and
|
||||||
|
<function>nallocx<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
|
||||||
|
specify one or more of the following:
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><constant>MALLOCX_LG_ALIGN(<parameter>la</parameter>)
|
||||||
|
</constant></term>
|
||||||
|
|
||||||
<para>The <function>malloc_usable_size<parameter/></function> function
|
<listitem><para>Align the memory allocation to start at an address
|
||||||
returns the usable size of the allocation pointed to by
|
that is a multiple of <code language="C">(1 <<
|
||||||
<parameter>ptr</parameter>. The return value may be larger than the size
|
<parameter>la</parameter>)</code>. This macro does not validate
|
||||||
that was requested during allocation. The
|
that <parameter>la</parameter> is within the valid
|
||||||
<function>malloc_usable_size<parameter/></function> function is not a
|
range.</para></listitem>
|
||||||
mechanism for in-place <function>realloc<parameter/></function>; rather
|
</varlistentry>
|
||||||
it is provided solely as a tool for introspection purposes. Any
|
<varlistentry>
|
||||||
discrepancy between the requested allocation size and the size reported
|
<term><constant>MALLOCX_ALIGN(<parameter>a</parameter>)
|
||||||
by <function>malloc_usable_size<parameter/></function> should not be
|
</constant></term>
|
||||||
depended on, since such behavior is entirely implementation-dependent.
|
|
||||||
|
<listitem><para>Align the memory allocation to start at an address
|
||||||
|
that is a multiple of <parameter>a</parameter>, where
|
||||||
|
<parameter>a</parameter> is a power of two. This macro does not
|
||||||
|
validate that <parameter>a</parameter> is a power of 2.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><constant>MALLOCX_ZERO</constant></term>
|
||||||
|
|
||||||
|
<listitem><para>Initialize newly allocated memory to contain zero
|
||||||
|
bytes. In the growing reallocation case, the real size prior to
|
||||||
|
reallocation defines the boundary between untouched bytes and those
|
||||||
|
that are initialized to contain zero bytes. If this macro is
|
||||||
|
absent, newly allocated memory is uninitialized.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><constant>MALLOCX_ARENA(<parameter>a</parameter>)
|
||||||
|
</constant></term>
|
||||||
|
|
||||||
|
<listitem><para>Use the arena specified by the index
|
||||||
|
<parameter>a</parameter> (and by necessity bypass the thread
|
||||||
|
cache). This macro has no effect for huge regions, nor for regions
|
||||||
|
that were allocated via an arena other than the one specified.
|
||||||
|
This macro does not validate that <parameter>a</parameter>
|
||||||
|
specifies an arena index in the valid range.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>The <function>malloc_stats_print<parameter/></function> function
|
<para>The <function>mallocx<parameter/></function> function allocates at
|
||||||
writes human-readable summary statistics via the
|
least <parameter>size</parameter> bytes of memory, and returns a pointer
|
||||||
<parameter>write_cb</parameter> callback function pointer and
|
to the base address of the allocation. Behavior is undefined if
|
||||||
<parameter>cbopaque</parameter> data passed to
|
<parameter>size</parameter> is <constant>0</constant>.</para>
|
||||||
<parameter>write_cb</parameter>, or
|
|
||||||
<function>malloc_message<parameter/></function> if
|
<para>The <function>rallocx<parameter/></function> function resizes the
|
||||||
<parameter>write_cb</parameter> is <constant>NULL</constant>. This
|
allocation at <parameter>ptr</parameter> to be at least
|
||||||
function can be called repeatedly. General information that never
|
<parameter>size</parameter> bytes, and returns a pointer to the base
|
||||||
changes during execution can be omitted by specifying "g" as a character
|
address of the resulting allocation, which may or may not have moved from
|
||||||
within the <parameter>opts</parameter> string. Note that
|
its original location. Behavior is undefined if
|
||||||
<function>malloc_message<parameter/></function> uses the
|
<parameter>size</parameter> is <constant>0</constant>.</para>
|
||||||
<function>mallctl*<parameter/></function> functions internally, so
|
|
||||||
inconsistent statistics can be reported if multiple threads use these
|
<para>The <function>xallocx<parameter/></function> function resizes the
|
||||||
functions simultaneously. If <option>--enable-stats</option> is
|
allocation at <parameter>ptr</parameter> in place to be at least
|
||||||
specified during configuration, “m” and “a” can
|
<parameter>size</parameter> bytes, and returns the real size of the
|
||||||
be specified to omit merged arena and per arena statistics, respectively;
|
allocation. If <parameter>extra</parameter> is non-zero, an attempt is
|
||||||
“b” and “l” can be specified to omit per size
|
made to resize the allocation to be at least <code
|
||||||
class statistics for bins and large objects, respectively. Unrecognized
|
language="C">(<parameter>size</parameter> +
|
||||||
characters are silently ignored. Note that thread caching may prevent
|
<parameter>extra</parameter>)</code> bytes, though inability to allocate
|
||||||
some statistics from being completely up to date, since extra locking
|
the extra byte(s) will not by itself result in failure to resize.
|
||||||
would be required to merge counters that track thread cache operations.
|
Behavior is undefined if <parameter>size</parameter> is
|
||||||
</para>
|
<constant>0</constant>, or if <code
|
||||||
|
language="C">(<parameter>size</parameter> + <parameter>extra</parameter>
|
||||||
|
> <constant>SIZE_T_MAX</constant>)</code>.</para>
|
||||||
|
|
||||||
|
<para>The <function>sallocx<parameter/></function> function returns the
|
||||||
|
real size of the allocation at <parameter>ptr</parameter>.</para>
|
||||||
|
|
||||||
|
<para>The <function>dallocx<parameter/></function> function causes the
|
||||||
|
memory referenced by <parameter>ptr</parameter> to be made available for
|
||||||
|
future allocations.</para>
|
||||||
|
|
||||||
|
<para>The <function>nallocx<parameter/></function> function allocates no
|
||||||
|
memory, but it performs the same size computation as the
|
||||||
|
<function>mallocx<parameter/></function> function, and returns the real
|
||||||
|
size of the allocation that would result from the equivalent
|
||||||
|
<function>mallocx<parameter/></function> function call. Behavior is
|
||||||
|
undefined if <parameter>size</parameter> is
|
||||||
|
<constant>0</constant>.</para>
|
||||||
|
|
||||||
<para>The <function>mallctl<parameter/></function> function provides a
|
<para>The <function>mallctl<parameter/></function> function provides a
|
||||||
general interface for introspecting the memory allocator, as well as
|
general interface for introspecting the memory allocator, as well as
|
||||||
@ -314,6 +411,41 @@ for (i = 0; i < nbins; i++) {
|
|||||||
mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0);
|
mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0);
|
||||||
/* Do something with bin_size... */
|
/* Do something with bin_size... */
|
||||||
}]]></programlisting></para>
|
}]]></programlisting></para>
|
||||||
|
|
||||||
|
<para>The <function>malloc_stats_print<parameter/></function> function
|
||||||
|
writes human-readable summary statistics via the
|
||||||
|
<parameter>write_cb</parameter> callback function pointer and
|
||||||
|
<parameter>cbopaque</parameter> data passed to
|
||||||
|
<parameter>write_cb</parameter>, or
|
||||||
|
<function>malloc_message<parameter/></function> if
|
||||||
|
<parameter>write_cb</parameter> is <constant>NULL</constant>. This
|
||||||
|
function can be called repeatedly. General information that never
|
||||||
|
changes during execution can be omitted by specifying "g" as a character
|
||||||
|
within the <parameter>opts</parameter> string. Note that
|
||||||
|
<function>malloc_message<parameter/></function> uses the
|
||||||
|
<function>mallctl*<parameter/></function> functions internally, so
|
||||||
|
inconsistent statistics can be reported if multiple threads use these
|
||||||
|
functions simultaneously. If <option>--enable-stats</option> is
|
||||||
|
specified during configuration, “m” and “a” can
|
||||||
|
be specified to omit merged arena and per arena statistics, respectively;
|
||||||
|
“b” and “l” can be specified to omit per size
|
||||||
|
class statistics for bins and large objects, respectively. Unrecognized
|
||||||
|
characters are silently ignored. Note that thread caching may prevent
|
||||||
|
some statistics from being completely up to date, since extra locking
|
||||||
|
would be required to merge counters that track thread cache operations.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>The <function>malloc_usable_size<parameter/></function> function
|
||||||
|
returns the usable size of the allocation pointed to by
|
||||||
|
<parameter>ptr</parameter>. The return value may be larger than the size
|
||||||
|
that was requested during allocation. The
|
||||||
|
<function>malloc_usable_size<parameter/></function> function is not a
|
||||||
|
mechanism for in-place <function>realloc<parameter/></function>; rather
|
||||||
|
it is provided solely as a tool for introspection purposes. Any
|
||||||
|
discrepancy between the requested allocation size and the size reported
|
||||||
|
by <function>malloc_usable_size<parameter/></function> should not be
|
||||||
|
depended on, since such behavior is entirely implementation-dependent.
|
||||||
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Experimental API</title>
|
<title>Experimental API</title>
|
||||||
@ -398,7 +530,7 @@ for (i = 0; i < nbins; i++) {
|
|||||||
<parameter>rsize</parameter> is not <constant>NULL</constant>. If
|
<parameter>rsize</parameter> is not <constant>NULL</constant>. If
|
||||||
<parameter>extra</parameter> is non-zero, an attempt is made to resize
|
<parameter>extra</parameter> is non-zero, an attempt is made to resize
|
||||||
the allocation to be at least <code
|
the allocation to be at least <code
|
||||||
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 <parameter>size</parameter> is <constant>0</constant>, or if
|
undefined if <parameter>size</parameter> is <constant>0</constant>, or if
|
||||||
@ -936,7 +1068,8 @@ for (i = 0; i < nbins; i++) {
|
|||||||
<listitem><para>Zero filling enabled/disabled. If enabled, each byte
|
<listitem><para>Zero filling enabled/disabled. If enabled, each byte
|
||||||
of uninitialized allocated memory will be initialized to 0. Note that
|
of uninitialized allocated memory will be initialized to 0. Note that
|
||||||
this initialization only happens once for each byte, so
|
this initialization only happens once for each byte, so
|
||||||
<function>realloc<parameter/></function> and
|
<function>realloc<parameter/></function>,
|
||||||
|
<function>rallocx<parameter/></function> and
|
||||||
<function>rallocm<parameter/></function> calls do not zero memory that
|
<function>rallocm<parameter/></function> calls do not zero memory that
|
||||||
was previously allocated. This is intended for debugging and will
|
was previously allocated. This is intended for debugging and will
|
||||||
impact performance negatively. This option is disabled by default.
|
impact performance negatively. This option is disabled by default.
|
||||||
@ -2039,9 +2172,26 @@ malloc_conf = "xmalloc:true";]]></programlisting>
|
|||||||
</refsect2>
|
</refsect2>
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Non-standard API</title>
|
<title>Non-standard API</title>
|
||||||
<para>The <function>malloc_usable_size<parameter/></function> function
|
<para>The <function>mallocx<parameter/></function> and
|
||||||
returns the usable size of the allocation pointed to by
|
<function>rallocx<parameter/></function> functions return a pointer to
|
||||||
<parameter>ptr</parameter>. </para>
|
the allocated memory if successful; otherwise a <constant>NULL</constant>
|
||||||
|
pointer is returned to indicate insufficient contiguous memory was
|
||||||
|
available to service the allocation request. </para>
|
||||||
|
|
||||||
|
<para>The <function>xallocx<parameter/></function> function returns the
|
||||||
|
real size of the resulting resized allocation pointed to by
|
||||||
|
<parameter>ptr</parameter>, which is a value less than
|
||||||
|
<parameter>size</parameter> if the allocation could not be adequately
|
||||||
|
grown in place. </para>
|
||||||
|
|
||||||
|
<para>The <function>sallocx<parameter/></function> function returns the
|
||||||
|
real size of the allocation pointed to by <parameter>ptr</parameter>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>The <function>nallocx<parameter/></function> returns the real size
|
||||||
|
that would result from a successful equivalent
|
||||||
|
<function>mallocx<parameter/></function> function call, or zero if
|
||||||
|
insufficient memory is available to perform the size computation. </para>
|
||||||
|
|
||||||
<para>The <function>mallctl<parameter/></function>,
|
<para>The <function>mallctl<parameter/></function>,
|
||||||
<function>mallctlnametomib<parameter/></function>, and
|
<function>mallctlnametomib<parameter/></function>, and
|
||||||
@ -2092,6 +2242,10 @@ malloc_conf = "xmalloc:true";]]></programlisting>
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>The <function>malloc_usable_size<parameter/></function> function
|
||||||
|
returns the usable size of the allocation pointed to by
|
||||||
|
<parameter>ptr</parameter>. </para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Experimental API</title>
|
<title>Experimental API</title>
|
||||||
|
@ -228,6 +228,7 @@ static const bool config_ivsalloc =
|
|||||||
|
|
||||||
#include "jemalloc/internal/jemalloc_internal_macros.h"
|
#include "jemalloc/internal/jemalloc_internal_macros.h"
|
||||||
|
|
||||||
|
#define MALLOCX_LG_ALIGN_MASK ((int)0x3f)
|
||||||
#define ALLOCM_LG_ALIGN_MASK ((int)0x3f)
|
#define ALLOCM_LG_ALIGN_MASK ((int)0x3f)
|
||||||
|
|
||||||
/* Smallest size class to support. */
|
/* Smallest size class to support. */
|
||||||
@ -731,22 +732,22 @@ choose_arena(arena_t *arena)
|
|||||||
#include "jemalloc/internal/quarantine.h"
|
#include "jemalloc/internal/quarantine.h"
|
||||||
|
|
||||||
#ifndef JEMALLOC_ENABLE_INLINE
|
#ifndef JEMALLOC_ENABLE_INLINE
|
||||||
void *imallocx(size_t size, bool try_tcache, arena_t *arena);
|
void *imalloct(size_t size, bool try_tcache, arena_t *arena);
|
||||||
void *imalloc(size_t size);
|
void *imalloc(size_t size);
|
||||||
void *icallocx(size_t size, bool try_tcache, arena_t *arena);
|
void *icalloct(size_t size, bool try_tcache, arena_t *arena);
|
||||||
void *icalloc(size_t size);
|
void *icalloc(size_t size);
|
||||||
void *ipallocx(size_t usize, size_t alignment, bool zero, bool try_tcache,
|
void *ipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache,
|
||||||
arena_t *arena);
|
arena_t *arena);
|
||||||
void *ipalloc(size_t usize, size_t alignment, bool zero);
|
void *ipalloc(size_t usize, size_t alignment, bool zero);
|
||||||
size_t isalloc(const void *ptr, bool demote);
|
size_t isalloc(const void *ptr, bool demote);
|
||||||
size_t ivsalloc(const void *ptr, bool demote);
|
size_t ivsalloc(const void *ptr, bool demote);
|
||||||
size_t u2rz(size_t usize);
|
size_t u2rz(size_t usize);
|
||||||
size_t p2rz(const void *ptr);
|
size_t p2rz(const void *ptr);
|
||||||
void idallocx(void *ptr, bool try_tcache);
|
void idalloct(void *ptr, bool try_tcache);
|
||||||
void idalloc(void *ptr);
|
void idalloc(void *ptr);
|
||||||
void iqallocx(void *ptr, bool try_tcache);
|
void iqalloct(void *ptr, bool try_tcache);
|
||||||
void iqalloc(void *ptr);
|
void iqalloc(void *ptr);
|
||||||
void *irallocx(void *ptr, size_t size, size_t extra, size_t alignment,
|
void *iralloct(void *ptr, size_t size, size_t extra, size_t alignment,
|
||||||
bool zero, bool no_move, bool try_tcache_alloc, bool try_tcache_dalloc,
|
bool zero, bool no_move, bool try_tcache_alloc, bool try_tcache_dalloc,
|
||||||
arena_t *arena);
|
arena_t *arena);
|
||||||
void *iralloc(void *ptr, size_t size, size_t extra, size_t alignment,
|
void *iralloc(void *ptr, size_t size, size_t extra, size_t alignment,
|
||||||
@ -756,7 +757,7 @@ malloc_tsd_protos(JEMALLOC_ATTR(unused), thread_allocated, thread_allocated_t)
|
|||||||
|
|
||||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
|
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
|
||||||
JEMALLOC_ALWAYS_INLINE void *
|
JEMALLOC_ALWAYS_INLINE void *
|
||||||
imallocx(size_t size, bool try_tcache, arena_t *arena)
|
imalloct(size_t size, bool try_tcache, arena_t *arena)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert(size != 0);
|
assert(size != 0);
|
||||||
@ -771,11 +772,11 @@ JEMALLOC_ALWAYS_INLINE void *
|
|||||||
imalloc(size_t size)
|
imalloc(size_t size)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (imallocx(size, true, NULL));
|
return (imalloct(size, true, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE void *
|
JEMALLOC_ALWAYS_INLINE void *
|
||||||
icallocx(size_t size, bool try_tcache, arena_t *arena)
|
icalloct(size_t size, bool try_tcache, arena_t *arena)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (size <= arena_maxclass)
|
if (size <= arena_maxclass)
|
||||||
@ -788,11 +789,11 @@ JEMALLOC_ALWAYS_INLINE void *
|
|||||||
icalloc(size_t size)
|
icalloc(size_t size)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (icallocx(size, true, NULL));
|
return (icalloct(size, true, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE void *
|
JEMALLOC_ALWAYS_INLINE void *
|
||||||
ipallocx(size_t usize, size_t alignment, bool zero, bool try_tcache,
|
ipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache,
|
||||||
arena_t *arena)
|
arena_t *arena)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
@ -820,7 +821,7 @@ JEMALLOC_ALWAYS_INLINE void *
|
|||||||
ipalloc(size_t usize, size_t alignment, bool zero)
|
ipalloc(size_t usize, size_t alignment, bool zero)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (ipallocx(usize, alignment, zero, true, NULL));
|
return (ipalloct(usize, alignment, zero, true, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -881,7 +882,7 @@ p2rz(const void *ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE void
|
JEMALLOC_ALWAYS_INLINE void
|
||||||
idallocx(void *ptr, bool try_tcache)
|
idalloct(void *ptr, bool try_tcache)
|
||||||
{
|
{
|
||||||
arena_chunk_t *chunk;
|
arena_chunk_t *chunk;
|
||||||
|
|
||||||
@ -898,28 +899,28 @@ JEMALLOC_ALWAYS_INLINE void
|
|||||||
idalloc(void *ptr)
|
idalloc(void *ptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
idallocx(ptr, true);
|
idalloct(ptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE void
|
JEMALLOC_ALWAYS_INLINE void
|
||||||
iqallocx(void *ptr, bool try_tcache)
|
iqalloct(void *ptr, bool try_tcache)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (config_fill && opt_quarantine)
|
if (config_fill && opt_quarantine)
|
||||||
quarantine(ptr);
|
quarantine(ptr);
|
||||||
else
|
else
|
||||||
idallocx(ptr, try_tcache);
|
idalloct(ptr, try_tcache);
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE void
|
JEMALLOC_ALWAYS_INLINE void
|
||||||
iqalloc(void *ptr)
|
iqalloc(void *ptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
iqallocx(ptr, true);
|
iqalloct(ptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE void *
|
JEMALLOC_ALWAYS_INLINE void *
|
||||||
irallocx(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
|
iralloct(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
|
||||||
bool no_move, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena)
|
bool no_move, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
@ -943,7 +944,7 @@ irallocx(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
|
|||||||
usize = sa2u(size + extra, alignment);
|
usize = sa2u(size + extra, alignment);
|
||||||
if (usize == 0)
|
if (usize == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
ret = ipallocx(usize, alignment, zero, try_tcache_alloc, arena);
|
ret = ipalloct(usize, alignment, zero, try_tcache_alloc, arena);
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
if (extra == 0)
|
if (extra == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -951,7 +952,7 @@ irallocx(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
|
|||||||
usize = sa2u(size, alignment);
|
usize = sa2u(size, alignment);
|
||||||
if (usize == 0)
|
if (usize == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
ret = ipallocx(usize, alignment, zero, try_tcache_alloc,
|
ret = ipalloct(usize, alignment, zero, try_tcache_alloc,
|
||||||
arena);
|
arena);
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -963,7 +964,7 @@ irallocx(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
|
|||||||
*/
|
*/
|
||||||
copysize = (size < oldsize) ? size : oldsize;
|
copysize = (size < oldsize) ? size : oldsize;
|
||||||
memcpy(ret, ptr, copysize);
|
memcpy(ret, ptr, copysize);
|
||||||
iqallocx(ptr, try_tcache_dalloc);
|
iqalloct(ptr, try_tcache_dalloc);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -992,7 +993,7 @@ iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
|
|||||||
bool no_move)
|
bool no_move)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (irallocx(ptr, size, extra, alignment, zero, no_move, true, true,
|
return (iralloct(ptr, size, extra, alignment, zero, no_move, true, true,
|
||||||
NULL));
|
NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,17 +207,17 @@ huge_ralloc_no_move
|
|||||||
huge_salloc
|
huge_salloc
|
||||||
iallocm
|
iallocm
|
||||||
icalloc
|
icalloc
|
||||||
icallocx
|
icalloct
|
||||||
idalloc
|
idalloc
|
||||||
idallocx
|
idalloct
|
||||||
imalloc
|
imalloc
|
||||||
imallocx
|
imalloct
|
||||||
ipalloc
|
ipalloc
|
||||||
ipallocx
|
ipalloct
|
||||||
iqalloc
|
iqalloc
|
||||||
iqallocx
|
iqalloct
|
||||||
iralloc
|
iralloc
|
||||||
irallocx
|
iralloct
|
||||||
isalloc
|
isalloc
|
||||||
isthreaded
|
isthreaded
|
||||||
ivsalloc
|
ivsalloc
|
||||||
|
@ -6,11 +6,17 @@ posix_memalign
|
|||||||
aligned_alloc
|
aligned_alloc
|
||||||
realloc
|
realloc
|
||||||
free
|
free
|
||||||
malloc_usable_size
|
mallocx
|
||||||
malloc_stats_print
|
rallocx
|
||||||
|
xallocx
|
||||||
|
sallocx
|
||||||
|
dallocx
|
||||||
|
nallocx
|
||||||
mallctl
|
mallctl
|
||||||
mallctlnametomib
|
mallctlnametomib
|
||||||
mallctlbymib
|
mallctlbymib
|
||||||
|
malloc_stats_print
|
||||||
|
malloc_usable_size
|
||||||
memalign
|
memalign
|
||||||
valloc
|
valloc
|
||||||
allocm
|
allocm
|
||||||
|
@ -8,6 +8,17 @@
|
|||||||
#define JEMALLOC_VERSION_NREV @jemalloc_version_nrev@
|
#define JEMALLOC_VERSION_NREV @jemalloc_version_nrev@
|
||||||
#define JEMALLOC_VERSION_GID "@jemalloc_version_gid@"
|
#define JEMALLOC_VERSION_GID "@jemalloc_version_gid@"
|
||||||
|
|
||||||
|
# define MALLOCX_LG_ALIGN(la) (la)
|
||||||
|
# if LG_SIZEOF_PTR == 2
|
||||||
|
# define MALLOCX_ALIGN(a) (ffs(a)-1)
|
||||||
|
# else
|
||||||
|
# define MALLOCX_ALIGN(a) \
|
||||||
|
((a < (size_t)INT_MAX) ? ffs(a)-1 : ffs(a>>32)+31)
|
||||||
|
# endif
|
||||||
|
# define MALLOCX_ZERO ((int)0x40)
|
||||||
|
/* Bias arena index bits so that 0 encodes "MALLOCX_ARENA() unspecified". */
|
||||||
|
# define MALLOCX_ARENA(a) ((int)(((a)+1) << 8))
|
||||||
|
|
||||||
#ifdef JEMALLOC_EXPERIMENTAL
|
#ifdef JEMALLOC_EXPERIMENTAL
|
||||||
# define ALLOCM_LG_ALIGN(la) (la)
|
# define ALLOCM_LG_ALIGN(la) (la)
|
||||||
# if LG_SIZEOF_PTR == 2
|
# if LG_SIZEOF_PTR == 2
|
||||||
@ -39,11 +50,17 @@
|
|||||||
# undef je_aligned_alloc
|
# undef je_aligned_alloc
|
||||||
# undef je_realloc
|
# undef je_realloc
|
||||||
# undef je_free
|
# undef je_free
|
||||||
# undef je_malloc_usable_size
|
# undef je_mallocx
|
||||||
# undef je_malloc_stats_print
|
# undef je_rallocx
|
||||||
|
# undef je_xallocx
|
||||||
|
# undef je_sallocx
|
||||||
|
# undef je_dallocx
|
||||||
|
# undef je_nallocx
|
||||||
# undef je_mallctl
|
# undef je_mallctl
|
||||||
# undef je_mallctlnametomib
|
# undef je_mallctlnametomib
|
||||||
# undef je_mallctlbymib
|
# undef je_mallctlbymib
|
||||||
|
# undef je_malloc_stats_print
|
||||||
|
# undef je_malloc_usable_size
|
||||||
# undef je_memalign
|
# undef je_memalign
|
||||||
# undef je_valloc
|
# undef je_valloc
|
||||||
# undef je_allocm
|
# undef je_allocm
|
||||||
|
@ -17,11 +17,17 @@
|
|||||||
# define aligned_alloc je_aligned_alloc
|
# define aligned_alloc je_aligned_alloc
|
||||||
# define realloc je_realloc
|
# define realloc je_realloc
|
||||||
# define free je_free
|
# define free je_free
|
||||||
# define malloc_usable_size je_malloc_usable_size
|
# define mallocx je_mallocx
|
||||||
# define malloc_stats_print je_malloc_stats_print
|
# define rallocx je_rallocx
|
||||||
|
# define xallocx je_xallocx
|
||||||
|
# define sallocx je_sallocx
|
||||||
|
# define dallocx je_dallocx
|
||||||
|
# define nallocx je_nallocx
|
||||||
# define mallctl je_mallctl
|
# define mallctl je_mallctl
|
||||||
# define mallctlnametomib je_mallctlnametomib
|
# define mallctlnametomib je_mallctlnametomib
|
||||||
# define mallctlbymib je_mallctlbymib
|
# define mallctlbymib je_mallctlbymib
|
||||||
|
# define malloc_stats_print je_malloc_stats_print
|
||||||
|
# define malloc_usable_size je_malloc_usable_size
|
||||||
# define memalign je_memalign
|
# define memalign je_memalign
|
||||||
# define valloc je_valloc
|
# define valloc je_valloc
|
||||||
# ifdef JEMALLOC_EXPERIMENTAL
|
# ifdef JEMALLOC_EXPERIMENTAL
|
||||||
@ -56,6 +62,12 @@
|
|||||||
# undef je_mallctlbymib
|
# undef je_mallctlbymib
|
||||||
# undef je_memalign
|
# undef je_memalign
|
||||||
# undef je_valloc
|
# undef je_valloc
|
||||||
|
# undef je_mallocx
|
||||||
|
# undef je_rallocx
|
||||||
|
# undef je_xallocx
|
||||||
|
# undef je_sallocx
|
||||||
|
# undef je_dallocx
|
||||||
|
# undef je_nallocx
|
||||||
# ifdef JEMALLOC_EXPERIMENTAL
|
# ifdef JEMALLOC_EXPERIMENTAL
|
||||||
# undef je_allocm
|
# undef je_allocm
|
||||||
# undef je_rallocm
|
# undef je_rallocm
|
||||||
|
@ -17,6 +17,25 @@ JEMALLOC_EXPORT void *@je_@aligned_alloc(size_t alignment, size_t size)
|
|||||||
JEMALLOC_EXPORT void *@je_@realloc(void *ptr, size_t size);
|
JEMALLOC_EXPORT void *@je_@realloc(void *ptr, size_t size);
|
||||||
JEMALLOC_EXPORT void @je_@free(void *ptr);
|
JEMALLOC_EXPORT void @je_@free(void *ptr);
|
||||||
|
|
||||||
|
JEMALLOC_EXPORT void *@je_@mallocx(size_t size, int flags);
|
||||||
|
JEMALLOC_EXPORT void *@je_@rallocx(void *ptr, size_t size, int flags);
|
||||||
|
JEMALLOC_EXPORT size_t @je_@xallocx(void *ptr, size_t size, size_t extra,
|
||||||
|
int flags);
|
||||||
|
JEMALLOC_EXPORT size_t @je_@sallocx(const void *ptr, int flags);
|
||||||
|
JEMALLOC_EXPORT void @je_@dallocx(void *ptr, int flags);
|
||||||
|
JEMALLOC_EXPORT size_t @je_@nallocx(size_t size, int flags);
|
||||||
|
|
||||||
|
JEMALLOC_EXPORT int @je_@mallctl(const char *name, void *oldp,
|
||||||
|
size_t *oldlenp, void *newp, size_t newlen);
|
||||||
|
JEMALLOC_EXPORT int @je_@mallctlnametomib(const char *name, size_t *mibp,
|
||||||
|
size_t *miblenp);
|
||||||
|
JEMALLOC_EXPORT int @je_@mallctlbymib(const size_t *mib, size_t miblen,
|
||||||
|
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||||
|
JEMALLOC_EXPORT void @je_@malloc_stats_print(void (*write_cb)(void *,
|
||||||
|
const char *), void *@je_@cbopaque, const char *opts);
|
||||||
|
JEMALLOC_EXPORT size_t @je_@malloc_usable_size(
|
||||||
|
JEMALLOC_USABLE_SIZE_CONST void *ptr);
|
||||||
|
|
||||||
#ifdef JEMALLOC_OVERRIDE_MEMALIGN
|
#ifdef JEMALLOC_OVERRIDE_MEMALIGN
|
||||||
JEMALLOC_EXPORT void * @je_@memalign(size_t alignment, size_t size)
|
JEMALLOC_EXPORT void * @je_@memalign(size_t alignment, size_t size)
|
||||||
JEMALLOC_ATTR(malloc);
|
JEMALLOC_ATTR(malloc);
|
||||||
@ -26,17 +45,6 @@ JEMALLOC_EXPORT void * @je_@memalign(size_t alignment, size_t size)
|
|||||||
JEMALLOC_EXPORT void * @je_@valloc(size_t size) JEMALLOC_ATTR(malloc);
|
JEMALLOC_EXPORT void * @je_@valloc(size_t size) JEMALLOC_ATTR(malloc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JEMALLOC_EXPORT size_t @je_@malloc_usable_size(
|
|
||||||
JEMALLOC_USABLE_SIZE_CONST void *ptr);
|
|
||||||
JEMALLOC_EXPORT void @je_@malloc_stats_print(void (*write_cb)(void *,
|
|
||||||
const char *), void *@je_@cbopaque, const char *opts);
|
|
||||||
JEMALLOC_EXPORT int @je_@mallctl(const char *name, void *oldp,
|
|
||||||
size_t *oldlenp, void *newp, size_t newlen);
|
|
||||||
JEMALLOC_EXPORT int @je_@mallctlnametomib(const char *name, size_t *mibp,
|
|
||||||
size_t *miblenp);
|
|
||||||
JEMALLOC_EXPORT int @je_@mallctlbymib(const size_t *mib, size_t miblen,
|
|
||||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
|
||||||
|
|
||||||
#ifdef JEMALLOC_EXPERIMENTAL
|
#ifdef JEMALLOC_EXPERIMENTAL
|
||||||
JEMALLOC_EXPORT int @je_@allocm(void **ptr, size_t *rsize, size_t size,
|
JEMALLOC_EXPORT int @je_@allocm(void **ptr, size_t *rsize, size_t size,
|
||||||
int flags) JEMALLOC_ATTR(nonnull(1));
|
int flags) JEMALLOC_ATTR(nonnull(1));
|
||||||
|
@ -2031,7 +2031,7 @@ arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size,
|
|||||||
size_t usize = sa2u(size + extra, alignment);
|
size_t usize = sa2u(size + extra, alignment);
|
||||||
if (usize == 0)
|
if (usize == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
ret = ipallocx(usize, alignment, zero, try_tcache_alloc, arena);
|
ret = ipalloct(usize, alignment, zero, try_tcache_alloc, arena);
|
||||||
} else
|
} else
|
||||||
ret = arena_malloc(arena, size + extra, zero, try_tcache_alloc);
|
ret = arena_malloc(arena, size + extra, zero, try_tcache_alloc);
|
||||||
|
|
||||||
@ -2043,7 +2043,7 @@ arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size,
|
|||||||
size_t usize = sa2u(size, alignment);
|
size_t usize = sa2u(size, alignment);
|
||||||
if (usize == 0)
|
if (usize == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
ret = ipallocx(usize, alignment, zero, try_tcache_alloc,
|
ret = ipalloct(usize, alignment, zero, try_tcache_alloc,
|
||||||
arena);
|
arena);
|
||||||
} else
|
} else
|
||||||
ret = arena_malloc(arena, size, zero, try_tcache_alloc);
|
ret = arena_malloc(arena, size, zero, try_tcache_alloc);
|
||||||
@ -2061,7 +2061,7 @@ arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size,
|
|||||||
copysize = (size < oldsize) ? size : oldsize;
|
copysize = (size < oldsize) ? size : oldsize;
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize);
|
VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize);
|
||||||
memcpy(ret, ptr, copysize);
|
memcpy(ret, ptr, copysize);
|
||||||
iqallocx(ptr, try_tcache_dalloc);
|
iqalloct(ptr, try_tcache_dalloc);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
memcpy(ret, ptr, copysize);
|
memcpy(ret, ptr, copysize);
|
||||||
iqallocx(ptr, try_tcache_dalloc);
|
iqalloct(ptr, try_tcache_dalloc);
|
||||||
}
|
}
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
648
src/jemalloc.c
648
src/jemalloc.c
@ -1337,28 +1337,363 @@ JEMALLOC_EXPORT void *(* __memalign_hook)(size_t alignment, size_t size) =
|
|||||||
* Begin non-standard functions.
|
* Begin non-standard functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
size_t
|
JEMALLOC_ALWAYS_INLINE_C void *
|
||||||
je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)
|
imallocx(size_t usize, size_t alignment, bool zero, bool try_tcache,
|
||||||
|
arena_t *arena)
|
||||||
{
|
{
|
||||||
size_t ret;
|
|
||||||
|
assert(usize == ((alignment == 0) ? s2u(usize) : sa2u(usize,
|
||||||
|
alignment)));
|
||||||
|
|
||||||
|
if (alignment != 0)
|
||||||
|
return (ipalloct(usize, alignment, zero, try_tcache, arena));
|
||||||
|
else if (zero)
|
||||||
|
return (icalloct(usize, try_tcache, arena));
|
||||||
|
else
|
||||||
|
return (imalloct(usize, try_tcache, arena));
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
je_mallocx(size_t size, int flags)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
size_t usize;
|
||||||
|
size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)
|
||||||
|
& (SIZE_T_MAX-1));
|
||||||
|
bool zero = flags & MALLOCX_ZERO;
|
||||||
|
unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
|
||||||
|
arena_t *arena;
|
||||||
|
bool try_tcache;
|
||||||
|
|
||||||
|
assert(size != 0);
|
||||||
|
|
||||||
|
if (malloc_init())
|
||||||
|
goto label_oom;
|
||||||
|
|
||||||
|
if (arena_ind != UINT_MAX) {
|
||||||
|
arena = arenas[arena_ind];
|
||||||
|
try_tcache = false;
|
||||||
|
} else {
|
||||||
|
arena = NULL;
|
||||||
|
try_tcache = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);
|
||||||
|
if (usize == 0)
|
||||||
|
goto label_oom;
|
||||||
|
|
||||||
|
if (config_prof && opt_prof) {
|
||||||
|
prof_thr_cnt_t *cnt;
|
||||||
|
|
||||||
|
PROF_ALLOC_PREP(1, usize, cnt);
|
||||||
|
if (cnt == NULL)
|
||||||
|
goto label_oom;
|
||||||
|
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
|
||||||
|
SMALL_MAXCLASS) {
|
||||||
|
size_t usize_promoted = (alignment == 0) ?
|
||||||
|
s2u(SMALL_MAXCLASS+1) : sa2u(SMALL_MAXCLASS+1,
|
||||||
|
alignment);
|
||||||
|
assert(usize_promoted != 0);
|
||||||
|
p = imallocx(usize_promoted, alignment, zero,
|
||||||
|
try_tcache, arena);
|
||||||
|
if (p == NULL)
|
||||||
|
goto label_oom;
|
||||||
|
arena_prof_promoted(p, usize);
|
||||||
|
} else {
|
||||||
|
p = imallocx(usize, alignment, zero, try_tcache, arena);
|
||||||
|
if (p == NULL)
|
||||||
|
goto label_oom;
|
||||||
|
}
|
||||||
|
prof_malloc(p, usize, cnt);
|
||||||
|
} else {
|
||||||
|
p = imallocx(usize, alignment, zero, try_tcache, arena);
|
||||||
|
if (p == NULL)
|
||||||
|
goto label_oom;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config_stats) {
|
||||||
|
assert(usize == isalloc(p, config_prof));
|
||||||
|
thread_allocated_tsd_get()->allocated += usize;
|
||||||
|
}
|
||||||
|
UTRACE(0, size, p);
|
||||||
|
JEMALLOC_VALGRIND_MALLOC(true, p, usize, zero);
|
||||||
|
return (p);
|
||||||
|
label_oom:
|
||||||
|
if (config_xmalloc && opt_xmalloc) {
|
||||||
|
malloc_write("<jemalloc>: Error in mallocx(): out of memory\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
UTRACE(0, size, 0);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
je_rallocx(void *ptr, size_t size, int flags)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
size_t usize;
|
||||||
|
size_t old_size;
|
||||||
|
UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
|
||||||
|
size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)
|
||||||
|
& (SIZE_T_MAX-1));
|
||||||
|
bool zero = flags & MALLOCX_ZERO;
|
||||||
|
unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
|
||||||
|
bool try_tcache_alloc, try_tcache_dalloc;
|
||||||
|
arena_t *arena;
|
||||||
|
|
||||||
|
assert(ptr != NULL);
|
||||||
|
assert(size != 0);
|
||||||
|
assert(malloc_initialized || IS_INITIALIZER);
|
||||||
|
malloc_thread_init();
|
||||||
|
|
||||||
|
if (arena_ind != UINT_MAX) {
|
||||||
|
arena_chunk_t *chunk;
|
||||||
|
try_tcache_alloc = false;
|
||||||
|
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
|
||||||
|
try_tcache_dalloc = (chunk == ptr || chunk->arena !=
|
||||||
|
arenas[arena_ind]);
|
||||||
|
arena = arenas[arena_ind];
|
||||||
|
} else {
|
||||||
|
try_tcache_alloc = true;
|
||||||
|
try_tcache_dalloc = true;
|
||||||
|
arena = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config_prof && opt_prof) {
|
||||||
|
prof_thr_cnt_t *cnt;
|
||||||
|
|
||||||
|
usize = (alignment == 0) ? s2u(size) : sa2u(size,
|
||||||
|
alignment);
|
||||||
|
prof_ctx_t *old_ctx = prof_ctx_get(ptr);
|
||||||
|
old_size = isalloc(ptr, true);
|
||||||
|
if (config_valgrind && opt_valgrind)
|
||||||
|
old_rzsize = p2rz(ptr);
|
||||||
|
PROF_ALLOC_PREP(1, usize, cnt);
|
||||||
|
if (cnt == NULL)
|
||||||
|
goto label_oom;
|
||||||
|
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
|
||||||
|
SMALL_MAXCLASS) {
|
||||||
|
p = iralloct(ptr, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >=
|
||||||
|
size) ? 0 : size - (SMALL_MAXCLASS+1), alignment,
|
||||||
|
zero, false, try_tcache_alloc, try_tcache_dalloc,
|
||||||
|
arena);
|
||||||
|
if (p == NULL)
|
||||||
|
goto label_oom;
|
||||||
|
if (usize < PAGE)
|
||||||
|
arena_prof_promoted(p, usize);
|
||||||
|
} else {
|
||||||
|
p = iralloct(ptr, size, 0, alignment, zero, false,
|
||||||
|
try_tcache_alloc, try_tcache_dalloc, arena);
|
||||||
|
if (p == NULL)
|
||||||
|
goto label_oom;
|
||||||
|
}
|
||||||
|
prof_realloc(p, usize, cnt, old_size, old_ctx);
|
||||||
|
} else {
|
||||||
|
if (config_stats) {
|
||||||
|
old_size = isalloc(ptr, false);
|
||||||
|
if (config_valgrind && opt_valgrind)
|
||||||
|
old_rzsize = u2rz(old_size);
|
||||||
|
} else if (config_valgrind && opt_valgrind) {
|
||||||
|
old_size = isalloc(ptr, false);
|
||||||
|
old_rzsize = u2rz(old_size);
|
||||||
|
}
|
||||||
|
p = iralloct(ptr, size, 0, alignment, zero, false,
|
||||||
|
try_tcache_alloc, try_tcache_dalloc, arena);
|
||||||
|
if (p == NULL)
|
||||||
|
goto label_oom;
|
||||||
|
if (config_stats || (config_valgrind && opt_valgrind))
|
||||||
|
usize = isalloc(p, config_prof);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config_stats) {
|
||||||
|
thread_allocated_t *ta;
|
||||||
|
ta = thread_allocated_tsd_get();
|
||||||
|
ta->allocated += usize;
|
||||||
|
ta->deallocated += old_size;
|
||||||
|
}
|
||||||
|
UTRACE(ptr, size, p);
|
||||||
|
JEMALLOC_VALGRIND_REALLOC(p, usize, ptr, old_size, old_rzsize, zero);
|
||||||
|
return (p);
|
||||||
|
label_oom:
|
||||||
|
if (config_xmalloc && opt_xmalloc) {
|
||||||
|
malloc_write("<jemalloc>: Error in rallocx(): out of memory\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
UTRACE(ptr, size, 0);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
je_xallocx(void *ptr, size_t size, size_t extra, int flags)
|
||||||
|
{
|
||||||
|
size_t usize;
|
||||||
|
size_t old_size;
|
||||||
|
UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
|
||||||
|
size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)
|
||||||
|
& (SIZE_T_MAX-1));
|
||||||
|
bool zero = flags & MALLOCX_ZERO;
|
||||||
|
unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
|
||||||
|
bool try_tcache_alloc, try_tcache_dalloc;
|
||||||
|
arena_t *arena;
|
||||||
|
|
||||||
|
assert(ptr != NULL);
|
||||||
|
assert(size != 0);
|
||||||
|
assert(SIZE_T_MAX - size >= extra);
|
||||||
|
assert(malloc_initialized || IS_INITIALIZER);
|
||||||
|
malloc_thread_init();
|
||||||
|
|
||||||
|
if (arena_ind != UINT_MAX) {
|
||||||
|
arena_chunk_t *chunk;
|
||||||
|
try_tcache_alloc = false;
|
||||||
|
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
|
||||||
|
try_tcache_dalloc = (chunk == ptr || chunk->arena !=
|
||||||
|
arenas[arena_ind]);
|
||||||
|
arena = arenas[arena_ind];
|
||||||
|
} else {
|
||||||
|
try_tcache_alloc = true;
|
||||||
|
try_tcache_dalloc = true;
|
||||||
|
arena = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config_prof && opt_prof) {
|
||||||
|
prof_thr_cnt_t *cnt;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* usize isn't knowable before iralloc() returns when extra is
|
||||||
|
* non-zero. Therefore, compute its maximum possible value and
|
||||||
|
* use that in PROF_ALLOC_PREP() to decide whether to capture a
|
||||||
|
* backtrace. prof_realloc() will use the actual usize to
|
||||||
|
* decide whether to sample.
|
||||||
|
*/
|
||||||
|
size_t max_usize = (alignment == 0) ? s2u(size+extra) :
|
||||||
|
sa2u(size+extra, alignment);
|
||||||
|
prof_ctx_t *old_ctx = prof_ctx_get(ptr);
|
||||||
|
old_size = isalloc(ptr, true);
|
||||||
|
if (config_valgrind && opt_valgrind)
|
||||||
|
old_rzsize = p2rz(ptr);
|
||||||
|
PROF_ALLOC_PREP(1, max_usize, cnt);
|
||||||
|
if (cnt == NULL) {
|
||||||
|
usize = isalloc(ptr, config_prof);
|
||||||
|
goto label_not_moved;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Use minimum usize to determine whether promotion may happen.
|
||||||
|
*/
|
||||||
|
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U
|
||||||
|
&& ((alignment == 0) ? s2u(size) : sa2u(size, alignment))
|
||||||
|
<= SMALL_MAXCLASS) {
|
||||||
|
if (iralloct(ptr, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >=
|
||||||
|
size+extra) ? 0 : size+extra - (SMALL_MAXCLASS+1),
|
||||||
|
alignment, zero, true, try_tcache_alloc,
|
||||||
|
try_tcache_dalloc, arena) == NULL)
|
||||||
|
goto label_not_moved;
|
||||||
|
if (max_usize < PAGE) {
|
||||||
|
usize = max_usize;
|
||||||
|
arena_prof_promoted(ptr, usize);
|
||||||
|
} else
|
||||||
|
usize = isalloc(ptr, config_prof);
|
||||||
|
} else {
|
||||||
|
if (iralloct(ptr, size, extra, alignment, zero, true,
|
||||||
|
try_tcache_alloc, try_tcache_dalloc, arena) == NULL)
|
||||||
|
goto label_not_moved;
|
||||||
|
usize = isalloc(ptr, config_prof);
|
||||||
|
}
|
||||||
|
prof_realloc(ptr, usize, cnt, old_size, old_ctx);
|
||||||
|
} else {
|
||||||
|
if (config_stats) {
|
||||||
|
old_size = isalloc(ptr, false);
|
||||||
|
if (config_valgrind && opt_valgrind)
|
||||||
|
old_rzsize = u2rz(old_size);
|
||||||
|
} else if (config_valgrind && opt_valgrind) {
|
||||||
|
old_size = isalloc(ptr, false);
|
||||||
|
old_rzsize = u2rz(old_size);
|
||||||
|
}
|
||||||
|
if (iralloct(ptr, size, extra, alignment, zero, true,
|
||||||
|
try_tcache_alloc, try_tcache_dalloc, arena) == NULL) {
|
||||||
|
usize = isalloc(ptr, config_prof);
|
||||||
|
goto label_not_moved;
|
||||||
|
}
|
||||||
|
usize = isalloc(ptr, config_prof);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config_stats) {
|
||||||
|
thread_allocated_t *ta;
|
||||||
|
ta = thread_allocated_tsd_get();
|
||||||
|
ta->allocated += usize;
|
||||||
|
ta->deallocated += old_size;
|
||||||
|
}
|
||||||
|
JEMALLOC_VALGRIND_REALLOC(ptr, usize, ptr, old_size, old_rzsize, zero);
|
||||||
|
label_not_moved:
|
||||||
|
UTRACE(ptr, size, ptr);
|
||||||
|
return (usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
je_sallocx(const void *ptr, int flags)
|
||||||
|
{
|
||||||
|
size_t usize;
|
||||||
|
|
||||||
assert(malloc_initialized || IS_INITIALIZER);
|
assert(malloc_initialized || IS_INITIALIZER);
|
||||||
malloc_thread_init();
|
malloc_thread_init();
|
||||||
|
|
||||||
if (config_ivsalloc)
|
if (config_ivsalloc)
|
||||||
ret = ivsalloc(ptr, config_prof);
|
usize = ivsalloc(ptr, config_prof);
|
||||||
else
|
else {
|
||||||
ret = (ptr != NULL) ? isalloc(ptr, config_prof) : 0;
|
assert(ptr != NULL);
|
||||||
|
usize = isalloc(ptr, config_prof);
|
||||||
|
}
|
||||||
|
|
||||||
return (ret);
|
return (usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
je_dallocx(void *ptr, int flags)
|
||||||
const char *opts)
|
|
||||||
{
|
{
|
||||||
|
size_t usize;
|
||||||
|
UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);
|
||||||
|
unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
|
||||||
|
bool try_tcache;
|
||||||
|
|
||||||
stats_print(write_cb, cbopaque, opts);
|
assert(ptr != NULL);
|
||||||
|
assert(malloc_initialized || IS_INITIALIZER);
|
||||||
|
|
||||||
|
if (arena_ind != UINT_MAX) {
|
||||||
|
arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
|
||||||
|
try_tcache = (chunk == ptr || chunk->arena !=
|
||||||
|
arenas[arena_ind]);
|
||||||
|
} else
|
||||||
|
try_tcache = true;
|
||||||
|
|
||||||
|
UTRACE(ptr, 0, 0);
|
||||||
|
if (config_stats || config_valgrind)
|
||||||
|
usize = isalloc(ptr, config_prof);
|
||||||
|
if (config_prof && opt_prof) {
|
||||||
|
if (config_stats == false && config_valgrind == false)
|
||||||
|
usize = isalloc(ptr, config_prof);
|
||||||
|
prof_free(ptr, usize);
|
||||||
|
}
|
||||||
|
if (config_stats)
|
||||||
|
thread_allocated_tsd_get()->deallocated += usize;
|
||||||
|
if (config_valgrind && opt_valgrind)
|
||||||
|
rzsize = p2rz(ptr);
|
||||||
|
iqalloct(ptr, try_tcache);
|
||||||
|
JEMALLOC_VALGRIND_FREE(ptr, rzsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
je_nallocx(size_t size, int flags)
|
||||||
|
{
|
||||||
|
size_t usize;
|
||||||
|
size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)
|
||||||
|
& (SIZE_T_MAX-1));
|
||||||
|
|
||||||
|
assert(size != 0);
|
||||||
|
|
||||||
|
if (malloc_init())
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);
|
||||||
|
return (usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1393,6 +1728,30 @@ je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
|||||||
return (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen));
|
return (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
||||||
|
const char *opts)
|
||||||
|
{
|
||||||
|
|
||||||
|
stats_print(write_cb, cbopaque, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)
|
||||||
|
{
|
||||||
|
size_t ret;
|
||||||
|
|
||||||
|
assert(malloc_initialized || IS_INITIALIZER);
|
||||||
|
malloc_thread_init();
|
||||||
|
|
||||||
|
if (config_ivsalloc)
|
||||||
|
ret = ivsalloc(ptr, config_prof);
|
||||||
|
else
|
||||||
|
ret = (ptr != NULL) ? isalloc(ptr, config_prof) : 0;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* End non-standard functions.
|
* End non-standard functions.
|
||||||
*/
|
*/
|
||||||
@ -1402,284 +1761,65 @@ je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
|||||||
*/
|
*/
|
||||||
#ifdef JEMALLOC_EXPERIMENTAL
|
#ifdef JEMALLOC_EXPERIMENTAL
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE_C void *
|
|
||||||
iallocm(size_t usize, size_t alignment, bool zero, bool try_tcache,
|
|
||||||
arena_t *arena)
|
|
||||||
{
|
|
||||||
|
|
||||||
assert(usize == ((alignment == 0) ? s2u(usize) : sa2u(usize,
|
|
||||||
alignment)));
|
|
||||||
|
|
||||||
if (alignment != 0)
|
|
||||||
return (ipallocx(usize, alignment, zero, try_tcache, arena));
|
|
||||||
else if (zero)
|
|
||||||
return (icallocx(usize, try_tcache, arena));
|
|
||||||
else
|
|
||||||
return (imallocx(usize, try_tcache, arena));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
je_allocm(void **ptr, size_t *rsize, size_t size, int flags)
|
je_allocm(void **ptr, size_t *rsize, size_t size, int flags)
|
||||||
{
|
{
|
||||||
void *p;
|
void *p;
|
||||||
size_t usize;
|
|
||||||
size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK)
|
|
||||||
& (SIZE_T_MAX-1));
|
|
||||||
bool zero = flags & ALLOCM_ZERO;
|
|
||||||
unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
|
|
||||||
arena_t *arena;
|
|
||||||
bool try_tcache;
|
|
||||||
|
|
||||||
assert(ptr != NULL);
|
assert(ptr != NULL);
|
||||||
assert(size != 0);
|
|
||||||
|
|
||||||
if (malloc_init())
|
p = je_mallocx(size, flags);
|
||||||
goto label_oom;
|
|
||||||
|
|
||||||
if (arena_ind != UINT_MAX) {
|
|
||||||
arena = arenas[arena_ind];
|
|
||||||
try_tcache = false;
|
|
||||||
} else {
|
|
||||||
arena = NULL;
|
|
||||||
try_tcache = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);
|
|
||||||
if (usize == 0)
|
|
||||||
goto label_oom;
|
|
||||||
|
|
||||||
if (config_prof && opt_prof) {
|
|
||||||
prof_thr_cnt_t *cnt;
|
|
||||||
|
|
||||||
PROF_ALLOC_PREP(1, usize, cnt);
|
|
||||||
if (cnt == NULL)
|
|
||||||
goto label_oom;
|
|
||||||
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
|
|
||||||
SMALL_MAXCLASS) {
|
|
||||||
size_t usize_promoted = (alignment == 0) ?
|
|
||||||
s2u(SMALL_MAXCLASS+1) : sa2u(SMALL_MAXCLASS+1,
|
|
||||||
alignment);
|
|
||||||
assert(usize_promoted != 0);
|
|
||||||
p = iallocm(usize_promoted, alignment, zero,
|
|
||||||
try_tcache, arena);
|
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
goto label_oom;
|
|
||||||
arena_prof_promoted(p, usize);
|
|
||||||
} else {
|
|
||||||
p = iallocm(usize, alignment, zero, try_tcache, arena);
|
|
||||||
if (p == NULL)
|
|
||||||
goto label_oom;
|
|
||||||
}
|
|
||||||
prof_malloc(p, usize, cnt);
|
|
||||||
} else {
|
|
||||||
p = iallocm(usize, alignment, zero, try_tcache, arena);
|
|
||||||
if (p == NULL)
|
|
||||||
goto label_oom;
|
|
||||||
}
|
|
||||||
if (rsize != NULL)
|
|
||||||
*rsize = usize;
|
|
||||||
|
|
||||||
*ptr = p;
|
|
||||||
if (config_stats) {
|
|
||||||
assert(usize == isalloc(p, config_prof));
|
|
||||||
thread_allocated_tsd_get()->allocated += usize;
|
|
||||||
}
|
|
||||||
UTRACE(0, size, p);
|
|
||||||
JEMALLOC_VALGRIND_MALLOC(true, p, usize, zero);
|
|
||||||
return (ALLOCM_SUCCESS);
|
|
||||||
label_oom:
|
|
||||||
if (config_xmalloc && opt_xmalloc) {
|
|
||||||
malloc_write("<jemalloc>: Error in allocm(): "
|
|
||||||
"out of memory\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
*ptr = NULL;
|
|
||||||
UTRACE(0, size, 0);
|
|
||||||
return (ALLOCM_ERR_OOM);
|
return (ALLOCM_ERR_OOM);
|
||||||
|
if (rsize != NULL)
|
||||||
|
*rsize = isalloc(p, config_prof);
|
||||||
|
*ptr = p;
|
||||||
|
return (ALLOCM_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
je_rallocm(void **ptr, size_t *rsize, size_t size, size_t extra, int flags)
|
je_rallocm(void **ptr, size_t *rsize, size_t size, size_t extra, int flags)
|
||||||
{
|
{
|
||||||
void *p, *q;
|
int ret;
|
||||||
size_t usize;
|
|
||||||
size_t old_size;
|
|
||||||
UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
|
|
||||||
size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK)
|
|
||||||
& (SIZE_T_MAX-1));
|
|
||||||
bool zero = flags & ALLOCM_ZERO;
|
|
||||||
bool no_move = flags & ALLOCM_NO_MOVE;
|
bool no_move = flags & ALLOCM_NO_MOVE;
|
||||||
unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
|
|
||||||
bool try_tcache_alloc, try_tcache_dalloc;
|
|
||||||
arena_t *arena;
|
|
||||||
|
|
||||||
assert(ptr != NULL);
|
assert(ptr != NULL);
|
||||||
assert(*ptr != NULL);
|
assert(*ptr != NULL);
|
||||||
assert(size != 0);
|
assert(size != 0);
|
||||||
assert(SIZE_T_MAX - size >= extra);
|
assert(SIZE_T_MAX - size >= extra);
|
||||||
assert(malloc_initialized || IS_INITIALIZER);
|
|
||||||
malloc_thread_init();
|
|
||||||
|
|
||||||
if (arena_ind != UINT_MAX) {
|
if (no_move) {
|
||||||
arena_chunk_t *chunk;
|
size_t usize = je_xallocx(*ptr, size, extra, flags);
|
||||||
try_tcache_alloc = false;
|
ret = (usize >= size) ? ALLOCM_SUCCESS : ALLOCM_ERR_NOT_MOVED;
|
||||||
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(*ptr);
|
|
||||||
try_tcache_dalloc = (chunk == *ptr || chunk->arena !=
|
|
||||||
arenas[arena_ind]);
|
|
||||||
arena = arenas[arena_ind];
|
|
||||||
} else {
|
|
||||||
try_tcache_alloc = true;
|
|
||||||
try_tcache_dalloc = true;
|
|
||||||
arena = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = *ptr;
|
|
||||||
if (config_prof && opt_prof) {
|
|
||||||
prof_thr_cnt_t *cnt;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* usize isn't knowable before iralloc() returns when extra is
|
|
||||||
* non-zero. Therefore, compute its maximum possible value and
|
|
||||||
* use that in PROF_ALLOC_PREP() to decide whether to capture a
|
|
||||||
* backtrace. prof_realloc() will use the actual usize to
|
|
||||||
* decide whether to sample.
|
|
||||||
*/
|
|
||||||
size_t max_usize = (alignment == 0) ? s2u(size+extra) :
|
|
||||||
sa2u(size+extra, alignment);
|
|
||||||
prof_ctx_t *old_ctx = prof_ctx_get(p);
|
|
||||||
old_size = isalloc(p, true);
|
|
||||||
if (config_valgrind && opt_valgrind)
|
|
||||||
old_rzsize = p2rz(p);
|
|
||||||
PROF_ALLOC_PREP(1, max_usize, cnt);
|
|
||||||
if (cnt == NULL)
|
|
||||||
goto label_oom;
|
|
||||||
/*
|
|
||||||
* Use minimum usize to determine whether promotion may happen.
|
|
||||||
*/
|
|
||||||
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U
|
|
||||||
&& ((alignment == 0) ? s2u(size) : sa2u(size, alignment))
|
|
||||||
<= SMALL_MAXCLASS) {
|
|
||||||
q = irallocx(p, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >=
|
|
||||||
size+extra) ? 0 : size+extra - (SMALL_MAXCLASS+1),
|
|
||||||
alignment, zero, no_move, try_tcache_alloc,
|
|
||||||
try_tcache_dalloc, arena);
|
|
||||||
if (q == NULL)
|
|
||||||
goto label_err;
|
|
||||||
if (max_usize < PAGE) {
|
|
||||||
usize = max_usize;
|
|
||||||
arena_prof_promoted(q, usize);
|
|
||||||
} else
|
|
||||||
usize = isalloc(q, config_prof);
|
|
||||||
} else {
|
|
||||||
q = irallocx(p, size, extra, alignment, zero, no_move,
|
|
||||||
try_tcache_alloc, try_tcache_dalloc, arena);
|
|
||||||
if (q == NULL)
|
|
||||||
goto label_err;
|
|
||||||
usize = isalloc(q, config_prof);
|
|
||||||
}
|
|
||||||
prof_realloc(q, usize, cnt, old_size, old_ctx);
|
|
||||||
if (rsize != NULL)
|
if (rsize != NULL)
|
||||||
*rsize = usize;
|
*rsize = usize;
|
||||||
} else {
|
} else {
|
||||||
if (config_stats) {
|
void *p = je_rallocx(*ptr, size+extra, flags);
|
||||||
old_size = isalloc(p, false);
|
if (p != NULL) {
|
||||||
if (config_valgrind && opt_valgrind)
|
*ptr = p;
|
||||||
old_rzsize = u2rz(old_size);
|
ret = ALLOCM_SUCCESS;
|
||||||
} else if (config_valgrind && opt_valgrind) {
|
} else
|
||||||
old_size = isalloc(p, false);
|
ret = ALLOCM_ERR_OOM;
|
||||||
old_rzsize = u2rz(old_size);
|
if (rsize != NULL)
|
||||||
|
*rsize = isalloc(*ptr, config_prof);
|
||||||
}
|
}
|
||||||
q = irallocx(p, size, extra, alignment, zero, no_move,
|
return (ret);
|
||||||
try_tcache_alloc, try_tcache_dalloc, arena);
|
|
||||||
if (q == NULL)
|
|
||||||
goto label_err;
|
|
||||||
if (config_stats)
|
|
||||||
usize = isalloc(q, config_prof);
|
|
||||||
if (rsize != NULL) {
|
|
||||||
if (config_stats == false)
|
|
||||||
usize = isalloc(q, config_prof);
|
|
||||||
*rsize = usize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*ptr = q;
|
|
||||||
if (config_stats) {
|
|
||||||
thread_allocated_t *ta;
|
|
||||||
ta = thread_allocated_tsd_get();
|
|
||||||
ta->allocated += usize;
|
|
||||||
ta->deallocated += old_size;
|
|
||||||
}
|
|
||||||
UTRACE(p, size, q);
|
|
||||||
JEMALLOC_VALGRIND_REALLOC(q, usize, p, old_size, old_rzsize, zero);
|
|
||||||
return (ALLOCM_SUCCESS);
|
|
||||||
label_err:
|
|
||||||
if (no_move) {
|
|
||||||
UTRACE(p, size, q);
|
|
||||||
return (ALLOCM_ERR_NOT_MOVED);
|
|
||||||
}
|
|
||||||
label_oom:
|
|
||||||
if (config_xmalloc && opt_xmalloc) {
|
|
||||||
malloc_write("<jemalloc>: Error in rallocm(): "
|
|
||||||
"out of memory\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
UTRACE(p, size, 0);
|
|
||||||
return (ALLOCM_ERR_OOM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
je_sallocm(const void *ptr, size_t *rsize, int flags)
|
je_sallocm(const void *ptr, size_t *rsize, int flags)
|
||||||
{
|
{
|
||||||
size_t sz;
|
|
||||||
|
|
||||||
assert(malloc_initialized || IS_INITIALIZER);
|
|
||||||
malloc_thread_init();
|
|
||||||
|
|
||||||
if (config_ivsalloc)
|
|
||||||
sz = ivsalloc(ptr, config_prof);
|
|
||||||
else {
|
|
||||||
assert(ptr != NULL);
|
|
||||||
sz = isalloc(ptr, config_prof);
|
|
||||||
}
|
|
||||||
assert(rsize != NULL);
|
assert(rsize != NULL);
|
||||||
*rsize = sz;
|
*rsize = je_sallocx(ptr, flags);
|
||||||
|
|
||||||
return (ALLOCM_SUCCESS);
|
return (ALLOCM_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
je_dallocm(void *ptr, int flags)
|
je_dallocm(void *ptr, int flags)
|
||||||
{
|
{
|
||||||
size_t usize;
|
|
||||||
UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);
|
|
||||||
unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
|
|
||||||
bool try_tcache;
|
|
||||||
|
|
||||||
assert(ptr != NULL);
|
|
||||||
assert(malloc_initialized || IS_INITIALIZER);
|
|
||||||
|
|
||||||
if (arena_ind != UINT_MAX) {
|
|
||||||
arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
|
|
||||||
try_tcache = (chunk == ptr || chunk->arena !=
|
|
||||||
arenas[arena_ind]);
|
|
||||||
} else
|
|
||||||
try_tcache = true;
|
|
||||||
|
|
||||||
UTRACE(ptr, 0, 0);
|
|
||||||
if (config_stats || config_valgrind)
|
|
||||||
usize = isalloc(ptr, config_prof);
|
|
||||||
if (config_prof && opt_prof) {
|
|
||||||
if (config_stats == false && config_valgrind == false)
|
|
||||||
usize = isalloc(ptr, config_prof);
|
|
||||||
prof_free(ptr, usize);
|
|
||||||
}
|
|
||||||
if (config_stats)
|
|
||||||
thread_allocated_tsd_get()->deallocated += usize;
|
|
||||||
if (config_valgrind && opt_valgrind)
|
|
||||||
rzsize = p2rz(ptr);
|
|
||||||
iqallocx(ptr, try_tcache);
|
|
||||||
JEMALLOC_VALGRIND_FREE(ptr, rzsize);
|
|
||||||
|
|
||||||
|
je_dallocx(ptr, flags);
|
||||||
return (ALLOCM_SUCCESS);
|
return (ALLOCM_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1687,18 +1827,10 @@ int
|
|||||||
je_nallocm(size_t *rsize, size_t size, int flags)
|
je_nallocm(size_t *rsize, size_t size, int flags)
|
||||||
{
|
{
|
||||||
size_t usize;
|
size_t usize;
|
||||||
size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK)
|
|
||||||
& (SIZE_T_MAX-1));
|
|
||||||
|
|
||||||
assert(size != 0);
|
usize = je_nallocx(size, flags);
|
||||||
|
|
||||||
if (malloc_init())
|
|
||||||
return (ALLOCM_ERR_OOM);
|
|
||||||
|
|
||||||
usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);
|
|
||||||
if (usize == 0)
|
if (usize == 0)
|
||||||
return (ALLOCM_ERR_OOM);
|
return (ALLOCM_ERR_OOM);
|
||||||
|
|
||||||
if (rsize != NULL)
|
if (rsize != NULL)
|
||||||
*rsize = usize;
|
*rsize = usize;
|
||||||
return (ALLOCM_SUCCESS);
|
return (ALLOCM_SUCCESS);
|
||||||
|
@ -292,7 +292,7 @@ tcache_create(arena_t *arena)
|
|||||||
else if (size <= tcache_maxclass)
|
else if (size <= tcache_maxclass)
|
||||||
tcache = (tcache_t *)arena_malloc_large(arena, size, true);
|
tcache = (tcache_t *)arena_malloc_large(arena, size, true);
|
||||||
else
|
else
|
||||||
tcache = (tcache_t *)icallocx(size, false, arena);
|
tcache = (tcache_t *)icalloct(size, false, arena);
|
||||||
|
|
||||||
if (tcache == NULL)
|
if (tcache == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -366,7 +366,7 @@ tcache_destroy(tcache_t *tcache)
|
|||||||
|
|
||||||
arena_dalloc_large(arena, chunk, tcache);
|
arena_dalloc_large(arena, chunk, tcache);
|
||||||
} else
|
} else
|
||||||
idallocx(tcache, false);
|
idalloct(tcache, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -21,7 +21,7 @@ void
|
|||||||
malloc_tsd_dalloc(void *wrapper)
|
malloc_tsd_dalloc(void *wrapper)
|
||||||
{
|
{
|
||||||
|
|
||||||
idallocx(wrapper, false);
|
idalloct(wrapper, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
149
test/integration/mallocx.c
Normal file
149
test/integration/mallocx.c
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
|
#define CHUNK 0x400000
|
||||||
|
/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */
|
||||||
|
#define MAXALIGN ((size_t)0x2000000LU)
|
||||||
|
#define NITER 4
|
||||||
|
|
||||||
|
TEST_BEGIN(test_basic)
|
||||||
|
{
|
||||||
|
size_t nsz, rsz, sz;
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
sz = 42;
|
||||||
|
nsz = nallocx(sz, 0);
|
||||||
|
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
|
||||||
|
p = mallocx(sz, 0);
|
||||||
|
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
||||||
|
rsz = sallocx(p, 0);
|
||||||
|
assert_zu_ge(rsz, sz, "Real size smaller than expected");
|
||||||
|
assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch");
|
||||||
|
dallocx(p, 0);
|
||||||
|
|
||||||
|
p = mallocx(sz, 0);
|
||||||
|
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
||||||
|
dallocx(p, 0);
|
||||||
|
|
||||||
|
nsz = nallocx(sz, MALLOCX_ZERO);
|
||||||
|
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
|
||||||
|
p = mallocx(sz, MALLOCX_ZERO);
|
||||||
|
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
||||||
|
rsz = sallocx(p, 0);
|
||||||
|
assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch");
|
||||||
|
dallocx(p, 0);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_alignment_errors)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
size_t nsz, sz, alignment;
|
||||||
|
|
||||||
|
#if LG_SIZEOF_PTR == 3
|
||||||
|
alignment = UINT64_C(0x8000000000000000);
|
||||||
|
sz = UINT64_C(0x8000000000000000);
|
||||||
|
#else
|
||||||
|
alignment = 0x80000000LU;
|
||||||
|
sz = 0x80000000LU;
|
||||||
|
#endif
|
||||||
|
nsz = nallocx(sz, MALLOCX_ALIGN(alignment));
|
||||||
|
assert_zu_eq(nsz, 0, "Expected error for nallocx(%zu, %#x)", sz,
|
||||||
|
MALLOCX_ALIGN(alignment));
|
||||||
|
p = mallocx(sz, MALLOCX_ALIGN(alignment));
|
||||||
|
assert_ptr_null(p, "Expected error for mallocx(%zu, %#x)", sz,
|
||||||
|
MALLOCX_ALIGN(alignment));
|
||||||
|
|
||||||
|
#if LG_SIZEOF_PTR == 3
|
||||||
|
alignment = UINT64_C(0x4000000000000000);
|
||||||
|
sz = UINT64_C(0x8400000000000001);
|
||||||
|
#else
|
||||||
|
alignment = 0x40000000LU;
|
||||||
|
sz = 0x84000001LU;
|
||||||
|
#endif
|
||||||
|
nsz = nallocx(sz, MALLOCX_ALIGN(alignment));
|
||||||
|
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
|
||||||
|
p = mallocx(sz, MALLOCX_ALIGN(alignment));
|
||||||
|
assert_ptr_null(p, "Expected error for mallocx(%zu, %#x)", sz,
|
||||||
|
MALLOCX_ALIGN(alignment));
|
||||||
|
|
||||||
|
alignment = 0x10LU;
|
||||||
|
#if LG_SIZEOF_PTR == 3
|
||||||
|
sz = UINT64_C(0xfffffffffffffff0);
|
||||||
|
#else
|
||||||
|
sz = 0xfffffff0LU;
|
||||||
|
#endif
|
||||||
|
nsz = nallocx(sz, MALLOCX_ALIGN(alignment));
|
||||||
|
assert_zu_eq(nsz, 0, "Expected error for nallocx(%zu, %#x)", sz,
|
||||||
|
MALLOCX_ALIGN(alignment));
|
||||||
|
nsz = nallocx(sz, MALLOCX_ALIGN(alignment));
|
||||||
|
assert_zu_eq(nsz, 0, "Expected error for nallocx(%zu, %#x)", sz,
|
||||||
|
MALLOCX_ALIGN(alignment));
|
||||||
|
p = mallocx(sz, MALLOCX_ALIGN(alignment));
|
||||||
|
assert_ptr_null(p, "Expected error for mallocx(%zu, %#x)", sz,
|
||||||
|
MALLOCX_ALIGN(alignment));
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_alignment_and_size)
|
||||||
|
{
|
||||||
|
size_t nsz, rsz, sz, alignment, total;
|
||||||
|
unsigned i;
|
||||||
|
void *ps[NITER];
|
||||||
|
|
||||||
|
for (i = 0; i < NITER; i++)
|
||||||
|
ps[i] = NULL;
|
||||||
|
|
||||||
|
for (alignment = 8;
|
||||||
|
alignment <= MAXALIGN;
|
||||||
|
alignment <<= 1) {
|
||||||
|
total = 0;
|
||||||
|
for (sz = 1;
|
||||||
|
sz < 3 * alignment && sz < (1U << 31);
|
||||||
|
sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
|
||||||
|
for (i = 0; i < NITER; i++) {
|
||||||
|
nsz = nallocx(sz, MALLOCX_ALIGN(alignment) |
|
||||||
|
MALLOCX_ZERO);
|
||||||
|
assert_zu_ne(nsz, 0,
|
||||||
|
"nallocx() error for alignment=%zu, "
|
||||||
|
"size=%zu (%#zx)", alignment, sz, sz);
|
||||||
|
ps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) |
|
||||||
|
MALLOCX_ZERO);
|
||||||
|
assert_ptr_not_null(ps[i],
|
||||||
|
"mallocx() error for alignment=%zu, "
|
||||||
|
"size=%zu (%#zx)", alignment, sz, sz);
|
||||||
|
rsz = sallocx(ps[i], 0);
|
||||||
|
assert_zu_ge(rsz, sz,
|
||||||
|
"Real size smaller than expected for "
|
||||||
|
"alignment=%zu, size=%zu", alignment, sz);
|
||||||
|
assert_zu_eq(nsz, rsz,
|
||||||
|
"nallocx()/sallocx() size mismatch for "
|
||||||
|
"alignment=%zu, size=%zu", alignment, sz);
|
||||||
|
assert_ptr_null(
|
||||||
|
(void *)((uintptr_t)ps[i] & (alignment-1)),
|
||||||
|
"%p inadequately aligned for"
|
||||||
|
" alignment=%zu, size=%zu", ps[i],
|
||||||
|
alignment, sz);
|
||||||
|
total += rsz;
|
||||||
|
if (total >= (MAXALIGN << 1))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (i = 0; i < NITER; i++) {
|
||||||
|
if (ps[i] != NULL) {
|
||||||
|
dallocx(ps[i], 0);
|
||||||
|
ps[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (test(
|
||||||
|
test_basic,
|
||||||
|
test_alignment_errors,
|
||||||
|
test_alignment_and_size));
|
||||||
|
}
|
@ -1,5 +1,3 @@
|
|||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "test/jemalloc_test.h"
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
TEST_BEGIN(test_same_size)
|
TEST_BEGIN(test_same_size)
|
||||||
|
51
test/integration/rallocx.c
Normal file
51
test/integration/rallocx.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
|
TEST_BEGIN(test_grow_and_shrink)
|
||||||
|
{
|
||||||
|
void *p, *q;
|
||||||
|
size_t tsz;
|
||||||
|
#define NCYCLES 3
|
||||||
|
unsigned i, j;
|
||||||
|
#define NSZS 2500
|
||||||
|
size_t szs[NSZS];
|
||||||
|
#define MAXSZ ZU(12 * 1024 * 1024)
|
||||||
|
|
||||||
|
p = mallocx(1, 0);
|
||||||
|
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
||||||
|
szs[0] = sallocx(p, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < NCYCLES; i++) {
|
||||||
|
for (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) {
|
||||||
|
q = rallocx(p, szs[j-1]+1, 0);
|
||||||
|
assert_ptr_not_null(q,
|
||||||
|
"Unexpected rallocx() error for size=%zu-->%zu",
|
||||||
|
szs[j-1], szs[j-1]+1);
|
||||||
|
szs[j] = sallocx(q, 0);
|
||||||
|
assert_zu_ne(szs[j], szs[j-1]+1,
|
||||||
|
"Expected size to at least: %zu", szs[j-1]+1);
|
||||||
|
p = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j--; j > 0; j--) {
|
||||||
|
q = rallocx(p, szs[j-1], 0);
|
||||||
|
assert_ptr_not_null(q,
|
||||||
|
"Unexpected rallocx() error for size=%zu-->%zu",
|
||||||
|
szs[j], szs[j-1]);
|
||||||
|
tsz = sallocx(q, 0);
|
||||||
|
assert_zu_eq(tsz, szs[j-1],
|
||||||
|
"Expected size=%zu, got size=%zu", szs[j-1], tsz);
|
||||||
|
p = q;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dallocx(p, 0);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (test(
|
||||||
|
test_grow_and_shrink));
|
||||||
|
}
|
59
test/integration/xallocx.c
Normal file
59
test/integration/xallocx.c
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
|
TEST_BEGIN(test_same_size)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
size_t sz, tsz;
|
||||||
|
|
||||||
|
p = mallocx(42, 0);
|
||||||
|
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
||||||
|
sz = sallocx(p, 0);
|
||||||
|
|
||||||
|
tsz = xallocx(p, sz, 0, 0);
|
||||||
|
assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
|
||||||
|
|
||||||
|
dallocx(p, 0);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_extra_no_move)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
size_t sz, tsz;
|
||||||
|
|
||||||
|
p = mallocx(42, 0);
|
||||||
|
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
||||||
|
sz = sallocx(p, 0);
|
||||||
|
|
||||||
|
tsz = xallocx(p, sz, sz-42, 0);
|
||||||
|
assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
|
||||||
|
|
||||||
|
dallocx(p, 0);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_no_move_fail)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
size_t sz, tsz;
|
||||||
|
|
||||||
|
p = mallocx(42, 0);
|
||||||
|
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
||||||
|
sz = sallocx(p, 0);
|
||||||
|
|
||||||
|
tsz = xallocx(p, sz + 5, 0, 0);
|
||||||
|
assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
|
||||||
|
|
||||||
|
dallocx(p, 0);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (test(
|
||||||
|
test_same_size,
|
||||||
|
test_extra_no_move,
|
||||||
|
test_no_move_fail));
|
||||||
|
}
|
@ -39,8 +39,7 @@ thd_receiver_start(void *arg)
|
|||||||
for (i = 0; i < (NSENDERS * NMSGS); i++) {
|
for (i = 0; i < (NSENDERS * NMSGS); i++) {
|
||||||
mq_msg_t *msg = mq_get(mq);
|
mq_msg_t *msg = mq_get(mq);
|
||||||
assert_ptr_not_null(msg, "mq_get() should never return NULL");
|
assert_ptr_not_null(msg, "mq_get() should never return NULL");
|
||||||
assert_d_eq(jet_dallocm(msg, 0), ALLOCM_SUCCESS,
|
jet_dallocx(msg, 0);
|
||||||
"Unexpected dallocm() failure");
|
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -54,8 +53,8 @@ thd_sender_start(void *arg)
|
|||||||
for (i = 0; i < NMSGS; i++) {
|
for (i = 0; i < NMSGS; i++) {
|
||||||
mq_msg_t *msg;
|
mq_msg_t *msg;
|
||||||
void *p;
|
void *p;
|
||||||
assert_d_eq(jet_allocm(&p, NULL, sizeof(mq_msg_t), 0),
|
p = jet_mallocx(sizeof(mq_msg_t), 0);
|
||||||
ALLOCM_SUCCESS, "Unexpected allocm() failure");
|
assert_ptr_not_null(p, "Unexpected allocm() failure");
|
||||||
msg = (mq_msg_t *)p;
|
msg = (mq_msg_t *)p;
|
||||||
mq_put(mq, msg);
|
mq_put(mq, msg);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user