summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Evans <je@fb.com>2012-03-13 19:55:21 (GMT)
committerJason Evans <je@fb.com>2012-03-13 19:55:21 (GMT)
commit0a0bbf63e5d9bc60d6854c6d46b437fbeebd1470 (patch)
tree13c89000186384510a4a9fb23e5bd8fadc0ccdbf
parent4c2faa8a7c42a47a6bea509f5a23234bc5a66d40 (diff)
downloadjemalloc-0a0bbf63e5d9bc60d6854c6d46b437fbeebd1470.zip
jemalloc-0a0bbf63e5d9bc60d6854c6d46b437fbeebd1470.tar.gz
jemalloc-0a0bbf63e5d9bc60d6854c6d46b437fbeebd1470.tar.bz2
Implement aligned_alloc().
Implement aligned_alloc(), which was added in the C11 standard. The function is weakly specified to the point that a minimally compliant implementation would be painful to use (size must be an integral multiple of alignment!), which in practice makes posix_memalign() a safer choice.
-rw-r--r--Makefile.in6
-rw-r--r--configure.ac2
-rw-r--r--doc/jemalloc.xml.in35
-rw-r--r--include/jemalloc/jemalloc.h.in3
-rw-r--r--include/jemalloc/jemalloc_defs.h.in1
-rw-r--r--src/jemalloc.c37
-rw-r--r--test/aligned_alloc.c123
-rw-r--r--test/aligned_alloc.exp25
8 files changed, 218 insertions, 14 deletions
diff --git a/Makefile.in b/Makefile.in
index 6286455..01ed083 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -63,9 +63,9 @@ DOCS_XML := @objroot@doc/jemalloc@install_suffix@.xml
DOCS_HTML := $(DOCS_XML:@objroot@%.xml=@srcroot@%.html)
DOCS_MAN3 := $(DOCS_XML:@objroot@%.xml=@srcroot@%.3)
DOCS := $(DOCS_HTML) $(DOCS_MAN3)
-CTESTS := @srcroot@test/allocated.c @srcroot@test/bitmap.c \
- @srcroot@test/mremap.c @srcroot@test/posix_memalign.c \
- @srcroot@test/thread_arena.c
+CTESTS := @srcroot@test/aligned_alloc.c @srcroot@test/allocated.c \
+ @srcroot@test/bitmap.c @srcroot@test/mremap.c \
+ @srcroot@test/posix_memalign.c @srcroot@test/thread_arena.c
ifeq (@enable_experimental@, 1)
CTESTS += @srcroot@test/allocm.c @srcroot@test/rallocm.c
endif
diff --git a/configure.ac b/configure.ac
index a5ca859..295e646 100644
--- a/configure.ac
+++ b/configure.ac
@@ -316,7 +316,7 @@ AC_PATH_PROG([AR], [ar], , [$PATH])
AC_PATH_PROG([LD], [ld], , [$PATH])
AC_PATH_PROG([AUTOCONF], [autoconf], , [$PATH])
-public_syms="malloc_conf malloc_message malloc calloc posix_memalign 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 malloc_usable_size malloc_stats_print mallctl mallctlnametomib mallctlbymib"
dnl Check for allocator-related functions that should be wrapped.
AC_CHECK_FUNC([memalign],
diff --git a/doc/jemalloc.xml.in b/doc/jemalloc.xml.in
index 74da409..926deaf 100644
--- a/doc/jemalloc.xml.in
+++ b/doc/jemalloc.xml.in
@@ -30,6 +30,7 @@
<refname>malloc</refname>
<refname>calloc</refname>
<refname>posix_memalign</refname>
+ <refname>aligned_alloc</refname>
<refname>realloc</refname>
<refname>free</refname>
<refname>malloc_usable_size</refname>
@@ -74,6 +75,11 @@
<paramdef>size_t <parameter>size</parameter></paramdef>
</funcprototype>
<funcprototype>
+ <funcdef>void *<function>aligned_alloc</function></funcdef>
+ <paramdef>size_t <parameter>alignment</parameter></paramdef>
+ <paramdef>size_t <parameter>size</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
<funcdef>void *<function>realloc</function></funcdef>
<paramdef>void *<parameter>ptr</parameter></paramdef>
<paramdef>size_t <parameter>size</parameter></paramdef>
@@ -190,6 +196,14 @@
<parameter>alignment</parameter> must be a power of 2 at least as large
as <code language="C">sizeof(<type>void *</type>)</code>.</para>
+ <para>The <function>aligned_alloc<parameter/></function> function
+ allocates <parameter>size</parameter> bytes of memory such that the
+ allocation's base address is an even multiple of
+ <parameter>alignment</parameter>. The requested
+ <parameter>alignment</parameter> must be a power of 2. Behavior is
+ undefined if <parameter>size</parameter> is not an integral multiple of
+ <parameter>alignment</parameter>.</para>
+
<para>The <function>realloc<parameter/></function> function changes the
size of the previously allocated memory referenced by
<parameter>ptr</parameter> to <parameter>size</parameter> bytes. The
@@ -1789,6 +1803,27 @@ malloc_conf = "xmalloc:true";]]></programlisting>
</variablelist>
</para>
+ <para>The <function>aligned_alloc<parameter/></function> function returns
+ a pointer to the allocated memory if successful; otherwise a
+ <constant>NULL</constant> pointer is returned and
+ <varname>errno</varname> is set. The
+ <function>aligned_alloc<parameter/></function> function will fail if:
+ <variablelist>
+ <varlistentry>
+ <term><errorname>EINVAL</errorname></term>
+
+ <listitem><para>The <parameter>alignment</parameter> parameter is
+ not a power of 2.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorname>ENOMEM</errorname></term>
+
+ <listitem><para>Memory allocation error.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
<para>The <function>realloc<parameter/></function> function returns a
pointer, possibly identical to <parameter>ptr</parameter>, to the
allocated memory if successful; otherwise a <constant>NULL</constant>
diff --git a/include/jemalloc/jemalloc.h.in b/include/jemalloc/jemalloc.h.in
index 742dadd..f0581db 100644
--- a/include/jemalloc/jemalloc.h.in
+++ b/include/jemalloc/jemalloc.h.in
@@ -43,6 +43,7 @@ void *je_malloc(size_t size) JEMALLOC_ATTR(malloc);
void *je_calloc(size_t num, size_t size) JEMALLOC_ATTR(malloc);
int je_posix_memalign(void **memptr, size_t alignment, size_t size)
JEMALLOC_ATTR(nonnull(1));
+void *je_aligned_alloc(size_t alignment, size_t size) JEMALLOC_ATTR(malloc);
void *je_realloc(void *ptr, size_t size);
void je_free(void *ptr);
@@ -82,6 +83,7 @@ int je_nallocm(size_t *rsize, size_t size, int flags);
#define malloc je_malloc
#define calloc je_calloc
#define posix_memalign je_posix_memalign
+#define aligned_alloc je_aligned_alloc
#define realloc je_realloc
#define free je_free
#define malloc_usable_size je_malloc_usable_size
@@ -113,6 +115,7 @@ int je_nallocm(size_t *rsize, size_t size, int flags);
#undef je_malloc
#undef je_calloc
#undef je_posix_memalign
+#undef je_aligned_alloc
#undef je_realloc
#undef je_free
#undef je_malloc_usable_size
diff --git a/include/jemalloc/jemalloc_defs.h.in b/include/jemalloc/jemalloc_defs.h.in
index 6b2b0d0..f8f80e6 100644
--- a/include/jemalloc/jemalloc_defs.h.in
+++ b/include/jemalloc/jemalloc_defs.h.in
@@ -16,6 +16,7 @@
#undef je_malloc
#undef je_calloc
#undef je_posix_memalign
+#undef je_aligned_alloc
#undef je_realloc
#undef je_free
#undef je_malloc_usable_size
diff --git a/src/jemalloc.c b/src/jemalloc.c
index f564b65..2f3f372 100644
--- a/src/jemalloc.c
+++ b/src/jemalloc.c
@@ -68,7 +68,7 @@ static void malloc_conf_error(const char *msg, const char *k, size_t klen,
static void malloc_conf_init(void);
static bool malloc_init_hard(void);
static int imemalign(void **memptr, size_t alignment, size_t size,
- bool enforce_min_alignment);
+ size_t min_alignment);
/******************************************************************************/
/*
@@ -851,7 +851,7 @@ JEMALLOC_ATTR(noinline)
#endif
static int
imemalign(void **memptr, size_t alignment, size_t size,
- bool enforce_min_alignment)
+ size_t min_alignment)
{
int ret;
size_t usize;
@@ -862,6 +862,8 @@ imemalign(void **memptr, size_t alignment, size_t size,
#endif
;
+ assert(min_alignment != 0);
+
if (malloc_init())
result = NULL;
else {
@@ -870,10 +872,10 @@ imemalign(void **memptr, size_t alignment, size_t size,
/* Make sure that alignment is a large enough power of 2. */
if (((alignment - 1) & alignment) != 0
- || (enforce_min_alignment && alignment < sizeof(void *))) {
+ || (alignment < min_alignment)) {
if (config_xmalloc && opt_xmalloc) {
- malloc_write("<jemalloc>: Error in "
- "posix_memalign(): invalid alignment\n");
+ malloc_write("<jemalloc>: Error allocating "
+ "aligned memory: invalid alignment\n");
abort();
}
result = NULL;
@@ -915,8 +917,8 @@ imemalign(void **memptr, size_t alignment, size_t size,
if (result == NULL) {
if (config_xmalloc && opt_xmalloc) {
- malloc_write("<jemalloc>: Error in posix_memalign(): "
- "out of memory\n");
+ malloc_write("<jemalloc>: Error allocating aligned "
+ "memory: out of memory\n");
abort();
}
ret = ENOMEM;
@@ -942,7 +944,22 @@ int
je_posix_memalign(void **memptr, size_t alignment, size_t size)
{
- return imemalign(memptr, alignment, size, true);
+ return imemalign(memptr, alignment, size, sizeof(void *));
+}
+
+JEMALLOC_ATTR(malloc)
+JEMALLOC_ATTR(visibility("default"))
+void *
+je_aligned_alloc(size_t alignment, size_t size)
+{
+ void *ret;
+ int err;
+
+ if ((err = imemalign(&ret, alignment, size, 1)) != 0) {
+ ret = NULL;
+ errno = err;
+ }
+ return (ret);
}
JEMALLOC_ATTR(malloc)
@@ -1196,7 +1213,7 @@ je_memalign(size_t alignment, size_t size)
= NULL
#endif
;
- imemalign(&ret, alignment, size, false);
+ imemalign(&ret, alignment, size, 1);
return (ret);
}
#endif
@@ -1212,7 +1229,7 @@ je_valloc(size_t size)
= NULL
#endif
;
- imemalign(&ret, PAGE_SIZE, size, false);
+ imemalign(&ret, PAGE_SIZE, size, 1);
return (ret);
}
#endif
diff --git a/test/aligned_alloc.c b/test/aligned_alloc.c
new file mode 100644
index 0000000..2a95604
--- /dev/null
+++ b/test/aligned_alloc.c
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#define JEMALLOC_MANGLE
+#include "jemalloc_test.h"
+
+#define CHUNK 0x400000
+/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */
+#define MAXALIGN ((size_t)0x2000000LU)
+#define NITER 4
+
+int
+main(void)
+{
+ size_t alignment, size, total;
+ unsigned i;
+ void *p, *ps[NITER];
+
+ fprintf(stderr, "Test begin\n");
+
+ /* Test error conditions. */
+ alignment = 0;
+ errno = 0;
+ p = aligned_alloc(alignment, 1);
+ if (p != NULL || errno != EINVAL) {
+ fprintf(stderr,
+ "Expected error for invalid alignment %zu\n", alignment);
+ }
+
+ for (alignment = sizeof(size_t); alignment < MAXALIGN;
+ alignment <<= 1) {
+ errno = 0;
+ p = aligned_alloc(alignment + 1, 1);
+ if (p != NULL || errno != EINVAL) {
+ fprintf(stderr,
+ "Expected error for invalid alignment %zu\n",
+ alignment + 1);
+ }
+ }
+
+#if LG_SIZEOF_PTR == 3
+ alignment = UINT64_C(0x8000000000000000);
+ size = UINT64_C(0x8000000000000000);
+#else
+ alignment = 0x80000000LU;
+ size = 0x80000000LU;
+#endif
+ errno = 0;
+ p = aligned_alloc(alignment, size);
+ if (p != NULL || errno != ENOMEM) {
+ fprintf(stderr,
+ "Expected error for aligned_alloc(%zu, %zu)\n",
+ alignment, size);
+ }
+
+#if LG_SIZEOF_PTR == 3
+ alignment = UINT64_C(0x4000000000000000);
+ size = UINT64_C(0x8400000000000001);
+#else
+ alignment = 0x40000000LU;
+ size = 0x84000001LU;
+#endif
+ errno = 0;
+ p = aligned_alloc(alignment, size);
+ if (p != NULL || errno != ENOMEM) {
+ fprintf(stderr,
+ "Expected error for aligned_alloc(%zu, %zu)\n",
+ alignment, size);
+ }
+
+ alignment = 0x10LU;
+#if LG_SIZEOF_PTR == 3
+ size = UINT64_C(0xfffffffffffffff0);
+#else
+ size = 0xfffffff0LU;
+#endif
+ errno = 0;
+ p = aligned_alloc(alignment, size);
+ if (p != NULL || errno != ENOMEM) {
+ fprintf(stderr,
+ "Expected error for aligned_alloc(&p, %zu, %zu)\n",
+ alignment, size);
+ }
+
+ for (i = 0; i < NITER; i++)
+ ps[i] = NULL;
+
+ for (alignment = 8;
+ alignment <= MAXALIGN;
+ alignment <<= 1) {
+ total = 0;
+ fprintf(stderr, "Alignment: %zu\n", alignment);
+ for (size = 1;
+ size < 3 * alignment && size < (1U << 31);
+ size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
+ for (i = 0; i < NITER; i++) {
+ ps[i] = aligned_alloc(alignment, size);
+ if (ps[i] == NULL) {
+ fprintf(stderr,
+ "Error for size %zu (%#zx): %s\n",
+ size, size, strerror(errno));
+ exit(1);
+ }
+ total += malloc_usable_size(ps[i]);
+ if (total >= (MAXALIGN << 1))
+ break;
+ }
+ for (i = 0; i < NITER; i++) {
+ if (ps[i] != NULL) {
+ free(ps[i]);
+ ps[i] = NULL;
+ }
+ }
+ }
+ }
+
+ fprintf(stderr, "Test end\n");
+ return (0);
+}
diff --git a/test/aligned_alloc.exp b/test/aligned_alloc.exp
new file mode 100644
index 0000000..b5061c7
--- /dev/null
+++ b/test/aligned_alloc.exp
@@ -0,0 +1,25 @@
+Test begin
+Alignment: 8
+Alignment: 16
+Alignment: 32
+Alignment: 64
+Alignment: 128
+Alignment: 256
+Alignment: 512
+Alignment: 1024
+Alignment: 2048
+Alignment: 4096
+Alignment: 8192
+Alignment: 16384
+Alignment: 32768
+Alignment: 65536
+Alignment: 131072
+Alignment: 262144
+Alignment: 524288
+Alignment: 1048576
+Alignment: 2097152
+Alignment: 4194304
+Alignment: 8388608
+Alignment: 16777216
+Alignment: 33554432
+Test end