mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-22 04:03:11 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1819ae581c | ||
|
|
1ba886fb69 | ||
|
|
46c0af68bd | ||
|
|
8a26eaca7f | ||
|
|
ff53631535 | ||
|
|
9c62ed44b0 | ||
|
|
82abf6fe69 | ||
|
|
e181f5aa76 | ||
|
|
e64b1b7be9 | ||
|
|
df3f27024f | ||
|
|
ada8447cf6 | ||
|
|
ab8c79fdaf | ||
|
|
e3f27cfced | ||
|
|
9480a23005 | ||
|
|
57fb8e94ae | ||
|
|
c2da2591be | ||
|
|
fbb31029a5 | ||
|
|
c2dcfd8ded | ||
|
|
67fd1e0700 | ||
|
|
20a8c78bfe | ||
|
|
4bbf8181f3 | ||
|
|
bf543df20c | ||
|
|
9e20df163c | ||
|
|
7709a64c59 | ||
|
|
b9ec5c9a00 | ||
|
|
b037a55f36 | ||
|
|
940fdfd5ee | ||
|
|
cb657e3170 | ||
|
|
ad47e8996e | ||
|
|
99b0fbbe69 | ||
|
|
302735f90d | ||
|
|
69e9fbb9c1 | ||
|
|
9326a301b8 | ||
|
|
ddd6bd4e99 | ||
|
|
526e4a59a2 | ||
|
|
2850e90d0d | ||
|
|
5f60afa01e | ||
|
|
a184d3fcde | ||
|
|
2b51a3e9e9 | ||
|
|
9c8baec0a3 |
48
ChangeLog
48
ChangeLog
@@ -3,8 +3,50 @@ bug fixes are all mentioned, but internal enhancements are omitted here for
|
||||
brevity (even though they are more fun to write about). Much more detail can be
|
||||
found in the git revision history:
|
||||
|
||||
http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git
|
||||
git://canonware.com/jemalloc.git
|
||||
https://github.com/jemalloc/jemalloc
|
||||
|
||||
* 3.6.0 (March 31, 2014)
|
||||
|
||||
This version contains a critical bug fix for a regression present in 3.5.0 and
|
||||
3.5.1.
|
||||
|
||||
Bug fixes:
|
||||
- Fix a regression in arena_chunk_alloc() that caused crashes during
|
||||
small/large allocation if chunk allocation failed. In the absence of this
|
||||
bug, chunk allocation failure would result in allocation failure, e.g. NULL
|
||||
return from malloc(). This regression was introduced in 3.5.0.
|
||||
- Fix backtracing for gcc intrinsics-based backtracing by specifying
|
||||
-fno-omit-frame-pointer to gcc. Note that the application (and all the
|
||||
libraries it links to) must also be compiled with this option for
|
||||
backtracing to be reliable.
|
||||
- Use dss allocation precedence for huge allocations as well as small/large
|
||||
allocations.
|
||||
- Fix test assertion failure message formatting. This bug did not manifect on
|
||||
x86_64 systems because of implementation subtleties in va_list.
|
||||
- Fix inconsequential test failures for hash and SFMT code.
|
||||
|
||||
New features:
|
||||
- Support heap profiling on FreeBSD. This feature depends on the proc
|
||||
filesystem being mounted during heap profile dumping.
|
||||
|
||||
* 3.5.1 (February 25, 2014)
|
||||
|
||||
This version primarily addresses minor bugs in test code.
|
||||
|
||||
Bug fixes:
|
||||
- Configure Solaris/Illumos to use MADV_FREE.
|
||||
- Fix junk filling for mremap(2)-based huge reallocation. This is only
|
||||
relevant if configuring with the --enable-mremap option specified.
|
||||
- Avoid compilation failure if 'restrict' C99 keyword is not supported by the
|
||||
compiler.
|
||||
- Add a configure test for SSE2 rather than assuming it is usable on i686
|
||||
systems. This fixes test compilation errors, especially on 32-bit Linux
|
||||
systems.
|
||||
- Fix mallctl argument size mismatches (size_t vs. uint64_t) in the stats unit
|
||||
test.
|
||||
- Fix/remove flawed alignment-related overflow tests.
|
||||
- Prevent compiler optimizations that could change backtraces in the
|
||||
prof_accum unit test.
|
||||
|
||||
* 3.5.0 (January 22, 2014)
|
||||
|
||||
@@ -16,7 +58,7 @@ found in the git revision history:
|
||||
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(). Note that *allocm() is
|
||||
allocm()/rallocm() share with posix_memalign(). Note that *allocm() is
|
||||
slated for removal in the next non-bugfix release.
|
||||
- Add support for LinuxThreads.
|
||||
|
||||
|
||||
17
Makefile.in
17
Makefile.in
@@ -128,6 +128,8 @@ TESTS_UNIT := $(srcroot)test/unit/bitmap.c \
|
||||
$(srcroot)test/unit/tsd.c \
|
||||
$(srcroot)test/unit/util.c \
|
||||
$(srcroot)test/unit/zero.c
|
||||
TESTS_UNIT_AUX := $(srcroot)test/unit/prof_accum_a.c \
|
||||
$(srcroot)test/unit/prof_accum_b.c
|
||||
TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \
|
||||
$(srcroot)test/integration/allocated.c \
|
||||
$(srcroot)test/integration/mallocx.c \
|
||||
@@ -139,7 +141,7 @@ TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \
|
||||
$(srcroot)test/integration/xallocx.c
|
||||
ifeq ($(enable_experimental), 1)
|
||||
TESTS_INTEGRATION += $(srcroot)test/integration/allocm.c \
|
||||
$(srcroot)test/integration/ALLOCM_ARENA.c \
|
||||
$(srcroot)test/integration/MALLOCX_ARENA.c \
|
||||
$(srcroot)test/integration/rallocm.c
|
||||
endif
|
||||
TESTS_STRESS :=
|
||||
@@ -155,9 +157,10 @@ C_TESTLIB_STRESS_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.stress.$(O))
|
||||
C_TESTLIB_OBJS := $(C_TESTLIB_UNIT_OBJS) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(C_TESTLIB_STRESS_OBJS)
|
||||
|
||||
TESTS_UNIT_OBJS := $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%.$(O))
|
||||
TESTS_UNIT_AUX_OBJS := $(TESTS_UNIT_AUX:$(srcroot)%.c=$(objroot)%.$(O))
|
||||
TESTS_INTEGRATION_OBJS := $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%.$(O))
|
||||
TESTS_STRESS_OBJS := $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%.$(O))
|
||||
TESTS_OBJS := $(TESTS_UNIT_OBJS) $(TESTS_INTEGRATION_OBJS) $(TESTS_STRESS_OBJS)
|
||||
TESTS_OBJS := $(TESTS_UNIT_OBJS) $(TESTS_UNIT_AUX_OBJS) $(TESTS_INTEGRATION_OBJS) $(TESTS_STRESS_OBJS)
|
||||
|
||||
.PHONY: all dist build_doc_html build_doc_man build_doc
|
||||
.PHONY: install_bin install_include install_lib
|
||||
@@ -206,6 +209,12 @@ $(C_TESTLIB_STRESS_OBJS): $(objroot)test/src/%.stress.$(O): $(srcroot)test/src/%
|
||||
$(C_TESTLIB_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST -DJEMALLOC_STRESS_TESTLIB
|
||||
$(C_TESTLIB_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include
|
||||
$(TESTS_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST
|
||||
$(TESTS_UNIT_AUX_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST
|
||||
define make-unit-link-dep
|
||||
$(1): TESTS_UNIT_LINK_OBJS += $(2)
|
||||
$(1): $(2)
|
||||
endef
|
||||
$(foreach test, $(TESTS_UNIT:$(srcroot)test/unit/%.c=$(objroot)test/unit/%$(EXE)), $(eval $(call make-unit-link-dep,$(test),$(filter $(test:%=%_a.$(O)) $(test:%=%_b.$(O)),$(TESTS_UNIT_AUX_OBJS)))))
|
||||
$(TESTS_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST
|
||||
$(TESTS_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST
|
||||
$(TESTS_OBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c
|
||||
@@ -248,7 +257,7 @@ $(STATIC_LIBS):
|
||||
@mkdir -p $(@D)
|
||||
$(AR) $(ARFLAGS)@AROUT@ $+
|
||||
|
||||
$(objroot)test/unit/%$(EXE): $(objroot)test/unit/%.$(O) $(C_JET_OBJS) $(C_TESTLIB_UNIT_OBJS)
|
||||
$(objroot)test/unit/%$(EXE): $(objroot)test/unit/%.$(O) $(TESTS_UNIT_LINK_OBJS) $(C_JET_OBJS) $(C_TESTLIB_UNIT_OBJS)
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS)
|
||||
|
||||
@@ -359,7 +368,7 @@ coverage: check
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src unit $(C_TESTLIB_UNIT_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src integration $(C_TESTLIB_INTEGRATION_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src stress $(C_TESTLIB_STRESS_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/unit unit $(TESTS_UNIT_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/unit unit $(TESTS_UNIT_OBJS) $(TESTS_UNIT_AUX_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/integration integration $(TESTS_INTEGRATION_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/stress integration $(TESTS_STRESS_OBJS)
|
||||
endif
|
||||
|
||||
30
bin/pprof
30
bin/pprof
@@ -4197,8 +4197,12 @@ sub FindLibrary {
|
||||
# For libc libraries, the copy in /usr/lib/debug contains debugging symbols
|
||||
sub DebuggingLibrary {
|
||||
my $file = shift;
|
||||
if ($file =~ m|^/| && -f "/usr/lib/debug$file") {
|
||||
return "/usr/lib/debug$file";
|
||||
if ($file =~ m|^/|) {
|
||||
if (-f "/usr/lib/debug$file") {
|
||||
return "/usr/lib/debug$file";
|
||||
} elsif (-f "/usr/lib/debug$file.debug") {
|
||||
return "/usr/lib/debug$file.debug";
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
@@ -4360,6 +4364,19 @@ sub ParseLibraries {
|
||||
$finish = HexExtend($2);
|
||||
$offset = $zero_offset;
|
||||
$lib = $3;
|
||||
}
|
||||
# FreeBSD 10.0 virtual memory map /proc/curproc/map as defined in
|
||||
# function procfs_doprocmap (sys/fs/procfs/procfs_map.c)
|
||||
#
|
||||
# Example:
|
||||
# 0x800600000 0x80061a000 26 0 0xfffff800035a0000 r-x 75 33 0x1004 COW NC vnode /libexec/ld-elf.s
|
||||
# o.1 NCH -1
|
||||
elsif ($l =~ /^(0x$h)\s(0x$h)\s\d+\s\d+\s0x$h\sr-x\s\d+\s\d+\s0x\d+\s(COW|NCO)\s(NC|NNC)\svnode\s(\S+\.so(\.\d+)*)/) {
|
||||
$start = HexExtend($1);
|
||||
$finish = HexExtend($2);
|
||||
$offset = $zero_offset;
|
||||
$lib = FindLibrary($5);
|
||||
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
@@ -4382,6 +4399,7 @@ sub ParseLibraries {
|
||||
}
|
||||
}
|
||||
|
||||
if($main::opt_debug) { printf STDERR "$start:$finish ($offset) $lib\n"; }
|
||||
push(@{$result}, [$lib, $start, $finish, $offset]);
|
||||
}
|
||||
|
||||
@@ -4589,6 +4607,12 @@ sub ExtractSymbols {
|
||||
my $finish = $lib->[2];
|
||||
my $offset = $lib->[3];
|
||||
|
||||
# Use debug library if it exists
|
||||
my $debug_libname = DebuggingLibrary($libname);
|
||||
if ($debug_libname) {
|
||||
$libname = $debug_libname;
|
||||
}
|
||||
|
||||
# Get list of pcs that belong in this library.
|
||||
my $contained = [];
|
||||
my ($start_pc_index, $finish_pc_index);
|
||||
@@ -5019,7 +5043,7 @@ sub GetProcedureBoundariesViaNm {
|
||||
|
||||
# Tag this routine with the starting address in case the image
|
||||
# has multiple occurrences of this routine. We use a syntax
|
||||
# that resembles template paramters that are automatically
|
||||
# that resembles template parameters that are automatically
|
||||
# stripped out by ShortFunctionName()
|
||||
$this_routine .= "<$start_val>";
|
||||
|
||||
|
||||
52
configure.ac
52
configure.ac
@@ -19,7 +19,9 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
]], [[
|
||||
return 0;
|
||||
]])],
|
||||
[je_cv_cflags_appended=$1]
|
||||
AC_MSG_RESULT([yes]),
|
||||
[je_cv_cflags_appended=]
|
||||
AC_MSG_RESULT([no])
|
||||
[CFLAGS="${TCFLAGS}"]
|
||||
)
|
||||
@@ -128,6 +130,9 @@ if test "x$CFLAGS" = "x" ; then
|
||||
no_CFLAGS="yes"
|
||||
if test "x$GCC" = "xyes" ; then
|
||||
JE_CFLAGS_APPEND([-std=gnu99])
|
||||
if test "x$je_cv_cflags_appended" = "x-std=gnu99" ; then
|
||||
AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT])
|
||||
fi
|
||||
JE_CFLAGS_APPEND([-Wall])
|
||||
JE_CFLAGS_APPEND([-pipe])
|
||||
JE_CFLAGS_APPEND([-g3])
|
||||
@@ -145,6 +150,11 @@ if test "x$EXTRA_CFLAGS" != "x" ; then
|
||||
fi
|
||||
AC_PROG_CPP
|
||||
|
||||
AC_C_BIGENDIAN([ac_cv_big_endian=1], [ac_cv_big_endian=0])
|
||||
if test "x${ac_cv_big_endian}" = "x1" ; then
|
||||
AC_DEFINE_UNQUOTED([JEMALLOC_BIG_ENDIAN], [ ])
|
||||
fi
|
||||
|
||||
AC_CHECK_SIZEOF([void *])
|
||||
if test "x${ac_cv_sizeof_void_p}" = "x8" ; then
|
||||
LG_SIZEOF_PTR=3
|
||||
@@ -193,21 +203,21 @@ CPU_SPINWAIT=""
|
||||
case "${host_cpu}" in
|
||||
i[[345]]86)
|
||||
;;
|
||||
i686)
|
||||
JE_COMPILABLE([__asm__], [], [[__asm__ volatile("pause"); return 0;]],
|
||||
[je_cv_asm])
|
||||
if test "x${je_cv_asm}" = "xyes" ; then
|
||||
i686|x86_64)
|
||||
JE_COMPILABLE([pause instruction], [],
|
||||
[[__asm__ volatile("pause"); return 0;]],
|
||||
[je_cv_pause])
|
||||
if test "x${je_cv_pause}" = "xyes" ; then
|
||||
CPU_SPINWAIT='__asm__ volatile("pause")'
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([HAVE_SSE2], [ ])
|
||||
;;
|
||||
x86_64)
|
||||
JE_COMPILABLE([__asm__ syntax], [],
|
||||
[[__asm__ volatile("pause"); return 0;]], [je_cv_asm])
|
||||
if test "x${je_cv_asm}" = "xyes" ; then
|
||||
CPU_SPINWAIT='__asm__ volatile("pause")'
|
||||
dnl emmintrin.h fails to compile unless MMX, SSE, and SSE2 are
|
||||
dnl supported.
|
||||
JE_COMPILABLE([SSE2 intrinsics], [
|
||||
#include <emmintrin.h>
|
||||
], [], [je_cv_sse2])
|
||||
if test "x${je_cv_sse2}" = "xyes" ; then
|
||||
AC_DEFINE_UNQUOTED([HAVE_SSE2], [ ])
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([HAVE_SSE2], [ ])
|
||||
;;
|
||||
powerpc)
|
||||
AC_DEFINE_UNQUOTED([HAVE_ALTIVEC], [ ])
|
||||
@@ -296,6 +306,7 @@ case "${host}" in
|
||||
*-*-solaris2*)
|
||||
CFLAGS="$CFLAGS"
|
||||
abi="elf"
|
||||
AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
|
||||
RPATH='-Wl,-R,$(1)'
|
||||
dnl Solaris needs this for sigwait().
|
||||
CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS"
|
||||
@@ -736,22 +747,6 @@ if test "x$backtrace_method" = "x" -a "x$enable_prof_libgcc" = "x1" \
|
||||
-a "x$GCC" = "xyes" ; then
|
||||
AC_CHECK_HEADERS([unwind.h], , [enable_prof_libgcc="0"])
|
||||
AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [LIBS="$LIBS -lgcc"], [enable_prof_libgcc="0"])
|
||||
dnl The following is conservative, in that it only has entries for CPUs on
|
||||
dnl which jemalloc has been tested.
|
||||
AC_MSG_CHECKING([libgcc-based backtracing reliability on ${host_cpu}])
|
||||
case "${host_cpu}" in
|
||||
i[[3456]]86)
|
||||
AC_MSG_RESULT([unreliable])
|
||||
enable_prof_libgcc="0";
|
||||
;;
|
||||
x86_64)
|
||||
AC_MSG_RESULT([reliable])
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT([unreliable])
|
||||
enable_prof_libgcc="0";
|
||||
;;
|
||||
esac
|
||||
if test "x${enable_prof_libgcc}" = "x1" ; then
|
||||
backtrace_method="libgcc"
|
||||
AC_DEFINE([JEMALLOC_PROF_LIBGCC], [ ])
|
||||
@@ -773,6 +768,7 @@ fi
|
||||
)
|
||||
if test "x$backtrace_method" = "x" -a "x$enable_prof_gcc" = "x1" \
|
||||
-a "x$GCC" = "xyes" ; then
|
||||
JE_CFLAGS_APPEND([-fno-omit-frame-pointer])
|
||||
backtrace_method="gcc intrinsics"
|
||||
AC_DEFINE([JEMALLOC_PROF_GCC], [ ])
|
||||
else
|
||||
|
||||
@@ -1439,8 +1439,12 @@ malloc_conf = "xmalloc:true";]]></programlisting>
|
||||
<listitem><para>Set the precedence of dss allocation as related to mmap
|
||||
allocation for arena <i>, or for all arenas if <i> equals
|
||||
<link
|
||||
linkend="arenas.narenas"><mallctl>arenas.narenas</mallctl></link>. See
|
||||
<link linkend="opt.dss"><mallctl>opt.dss</mallctl></link> for supported
|
||||
linkend="arenas.narenas"><mallctl>arenas.narenas</mallctl></link>. Note
|
||||
that even during huge allocation this setting is read from the arena
|
||||
that would be chosen for small or large allocation so that applications
|
||||
can depend on consistent dss versus mmap allocation regardless of
|
||||
allocation size. See <link
|
||||
linkend="opt.dss"><mallctl>opt.dss</mallctl></link> for supported
|
||||
settings.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -320,7 +320,7 @@ hash_x64_128(const void *key, const int len, const uint32_t seed,
|
||||
JEMALLOC_INLINE void
|
||||
hash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2])
|
||||
{
|
||||
#if (LG_SIZEOF_PTR == 3)
|
||||
#if (LG_SIZEOF_PTR == 3 && !defined(JEMALLOC_BIG_ENDIAN))
|
||||
hash_x64_128(key, len, seed, (uint64_t *)r_hash);
|
||||
#else
|
||||
uint64_t hashes[2];
|
||||
|
||||
@@ -17,18 +17,20 @@ extern size_t huge_allocated;
|
||||
/* Protects chunk-related data structures. */
|
||||
extern malloc_mutex_t huge_mtx;
|
||||
|
||||
void *huge_malloc(size_t size, bool zero);
|
||||
void *huge_palloc(size_t size, size_t alignment, bool zero);
|
||||
void *huge_malloc(size_t size, bool zero, dss_prec_t dss_prec);
|
||||
void *huge_palloc(size_t size, size_t alignment, bool zero,
|
||||
dss_prec_t dss_prec);
|
||||
bool huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size,
|
||||
size_t extra);
|
||||
void *huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
size_t alignment, bool zero, bool try_tcache_dalloc);
|
||||
size_t alignment, bool zero, bool try_tcache_dalloc, dss_prec_t dss_prec);
|
||||
#ifdef JEMALLOC_JET
|
||||
typedef void (huge_dalloc_junk_t)(void *, size_t);
|
||||
extern huge_dalloc_junk_t *huge_dalloc_junk;
|
||||
#endif
|
||||
void huge_dalloc(void *ptr, bool unmap);
|
||||
size_t huge_salloc(const void *ptr);
|
||||
dss_prec_t huge_dss_prec_get(arena_t *arena);
|
||||
prof_ctx_t *huge_prof_ctx_get(const void *ptr);
|
||||
void huge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx);
|
||||
bool huge_boot(void);
|
||||
|
||||
@@ -770,7 +770,7 @@ imalloct(size_t size, bool try_tcache, arena_t *arena)
|
||||
if (size <= arena_maxclass)
|
||||
return (arena_malloc(arena, size, false, try_tcache));
|
||||
else
|
||||
return (huge_malloc(size, false));
|
||||
return (huge_malloc(size, false, huge_dss_prec_get(arena)));
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE void *
|
||||
@@ -787,7 +787,7 @@ icalloct(size_t size, bool try_tcache, arena_t *arena)
|
||||
if (size <= arena_maxclass)
|
||||
return (arena_malloc(arena, size, true, try_tcache));
|
||||
else
|
||||
return (huge_malloc(size, true));
|
||||
return (huge_malloc(size, true, huge_dss_prec_get(arena)));
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE void *
|
||||
@@ -813,9 +813,9 @@ ipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache,
|
||||
ret = arena_palloc(choose_arena(arena), usize,
|
||||
alignment, zero);
|
||||
} else if (alignment <= chunksize)
|
||||
ret = huge_malloc(usize, zero);
|
||||
ret = huge_malloc(usize, zero, huge_dss_prec_get(arena));
|
||||
else
|
||||
ret = huge_palloc(usize, alignment, zero);
|
||||
ret = huge_palloc(usize, alignment, zero, huge_dss_prec_get(arena));
|
||||
}
|
||||
|
||||
assert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret);
|
||||
@@ -984,7 +984,7 @@ iralloct(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
|
||||
try_tcache_dalloc));
|
||||
} else {
|
||||
return (huge_ralloc(ptr, oldsize, size, extra,
|
||||
alignment, zero, try_tcache_dalloc));
|
||||
alignment, zero, try_tcache_dalloc, huge_dss_prec_get(arena)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -187,6 +187,12 @@
|
||||
*/
|
||||
#undef JEMALLOC_HAS_ALLOCA_H
|
||||
|
||||
/* C99 restrict keyword supported. */
|
||||
#undef JEMALLOC_HAS_RESTRICT
|
||||
|
||||
/* For use by hash code. */
|
||||
#undef JEMALLOC_BIG_ENDIAN
|
||||
|
||||
/* sizeof(int) == 2^LG_SIZEOF_INT. */
|
||||
#undef LG_SIZEOF_INT
|
||||
|
||||
|
||||
@@ -45,3 +45,7 @@
|
||||
#ifndef __DECONST
|
||||
# define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
|
||||
#endif
|
||||
|
||||
#ifndef JEMALLOC_HAS_RESTRICT
|
||||
# define restrict
|
||||
#endif
|
||||
|
||||
@@ -197,6 +197,7 @@ huge_allocated
|
||||
huge_boot
|
||||
huge_dalloc
|
||||
huge_dalloc_junk
|
||||
huge_dss_prec_get
|
||||
huge_malloc
|
||||
huge_mtx
|
||||
huge_ndalloc
|
||||
|
||||
@@ -8,7 +8,11 @@ typedef struct prof_ctx_s prof_ctx_t;
|
||||
typedef struct prof_tdata_s prof_tdata_t;
|
||||
|
||||
/* Option defaults. */
|
||||
#define PROF_PREFIX_DEFAULT "jeprof"
|
||||
#ifdef JEMALLOC_PROF
|
||||
# define PROF_PREFIX_DEFAULT "jeprof"
|
||||
#else
|
||||
# define PROF_PREFIX_DEFAULT ""
|
||||
#endif
|
||||
#define LG_PROF_SAMPLE_DEFAULT 19
|
||||
#define LG_PROF_INTERVAL_DEFAULT -1
|
||||
|
||||
|
||||
25
src/arena.c
25
src/arena.c
@@ -358,9 +358,9 @@ arena_cactive_update(arena_t *arena, size_t add_pages, size_t sub_pages)
|
||||
{
|
||||
|
||||
if (config_stats) {
|
||||
ssize_t cactive_diff = CHUNK_CEILING((arena->nactive +
|
||||
add_pages) << LG_PAGE) - CHUNK_CEILING((arena->nactive -
|
||||
sub_pages) << LG_PAGE);
|
||||
ssize_t cactive_diff = CHUNK_CEILING((arena->nactive + add_pages
|
||||
- sub_pages) << LG_PAGE) - CHUNK_CEILING(arena->nactive <<
|
||||
LG_PAGE);
|
||||
if (cactive_diff != 0)
|
||||
stats_cactive_add(cactive_diff);
|
||||
}
|
||||
@@ -614,8 +614,11 @@ arena_chunk_alloc(arena_t *arena)
|
||||
|
||||
if (arena->spare != NULL)
|
||||
chunk = arena_chunk_init_spare(arena);
|
||||
else
|
||||
else {
|
||||
chunk = arena_chunk_init_hard(arena);
|
||||
if (chunk == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Insert the run into the runs_avail tree. */
|
||||
arena_avail_insert(arena, chunk, map_bias, chunk_npages-map_bias,
|
||||
@@ -1476,8 +1479,19 @@ arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind,
|
||||
ptr = arena_run_reg_alloc(run, &arena_bin_info[binind]);
|
||||
else
|
||||
ptr = arena_bin_malloc_hard(arena, bin);
|
||||
if (ptr == NULL)
|
||||
if (ptr == NULL) {
|
||||
/*
|
||||
* OOM. tbin->avail isn't yet filled down to its first
|
||||
* element, so the successful allocations (if any) must
|
||||
* be moved to the base of tbin->avail before bailing
|
||||
* out.
|
||||
*/
|
||||
if (i > 0) {
|
||||
memmove(tbin->avail, &tbin->avail[nfill - i],
|
||||
i * sizeof(void *));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (config_fill && opt_junk) {
|
||||
arena_alloc_junk_small(ptr, &arena_bin_info[binind],
|
||||
true);
|
||||
@@ -2476,7 +2490,6 @@ bin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size)
|
||||
bin_info->reg_interval) - pad_size;
|
||||
} while (try_hdr_size > try_redzone0_offset);
|
||||
} while (try_run_size <= arena_maxclass
|
||||
&& try_run_size <= arena_maxclass
|
||||
&& RUN_MAX_OVRHD * (bin_info->reg_interval << 3) >
|
||||
RUN_MAX_OVRHD_RELAX
|
||||
&& (try_redzone0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size
|
||||
|
||||
36
src/huge.c
36
src/huge.c
@@ -16,14 +16,14 @@ malloc_mutex_t huge_mtx;
|
||||
static extent_tree_t huge;
|
||||
|
||||
void *
|
||||
huge_malloc(size_t size, bool zero)
|
||||
huge_malloc(size_t size, bool zero, dss_prec_t dss_prec)
|
||||
{
|
||||
|
||||
return (huge_palloc(size, chunksize, zero));
|
||||
return (huge_palloc(size, chunksize, zero, dss_prec));
|
||||
}
|
||||
|
||||
void *
|
||||
huge_palloc(size_t size, size_t alignment, bool zero)
|
||||
huge_palloc(size_t size, size_t alignment, bool zero, dss_prec_t dss_prec)
|
||||
{
|
||||
void *ret;
|
||||
size_t csize;
|
||||
@@ -48,8 +48,7 @@ huge_palloc(size_t size, size_t alignment, bool zero)
|
||||
* it is possible to make correct junk/zero fill decisions below.
|
||||
*/
|
||||
is_zeroed = zero;
|
||||
ret = chunk_alloc(csize, alignment, false, &is_zeroed,
|
||||
chunk_dss_prec_get());
|
||||
ret = chunk_alloc(csize, alignment, false, &is_zeroed, dss_prec);
|
||||
if (ret == NULL) {
|
||||
base_node_dealloc(node);
|
||||
return (NULL);
|
||||
@@ -98,7 +97,7 @@ huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra)
|
||||
|
||||
void *
|
||||
huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
size_t alignment, bool zero, bool try_tcache_dalloc)
|
||||
size_t alignment, bool zero, bool try_tcache_dalloc, dss_prec_t dss_prec)
|
||||
{
|
||||
void *ret;
|
||||
size_t copysize;
|
||||
@@ -113,18 +112,18 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
* space and copying.
|
||||
*/
|
||||
if (alignment > chunksize)
|
||||
ret = huge_palloc(size + extra, alignment, zero);
|
||||
ret = huge_palloc(size + extra, alignment, zero, dss_prec);
|
||||
else
|
||||
ret = huge_malloc(size + extra, zero);
|
||||
ret = huge_malloc(size + extra, zero, dss_prec);
|
||||
|
||||
if (ret == NULL) {
|
||||
if (extra == 0)
|
||||
return (NULL);
|
||||
/* Try again, this time without extra. */
|
||||
if (alignment > chunksize)
|
||||
ret = huge_palloc(size, alignment, zero);
|
||||
ret = huge_palloc(size, alignment, zero, dss_prec);
|
||||
else
|
||||
ret = huge_malloc(size, zero);
|
||||
ret = huge_malloc(size, zero, dss_prec);
|
||||
|
||||
if (ret == NULL)
|
||||
return (NULL);
|
||||
@@ -171,6 +170,16 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
abort();
|
||||
memcpy(ret, ptr, copysize);
|
||||
chunk_dealloc_mmap(ptr, oldsize);
|
||||
} else if (config_fill && zero == false && opt_junk && oldsize
|
||||
< newsize) {
|
||||
/*
|
||||
* mremap(2) clobbers the original mapping, so
|
||||
* junk/zero filling is not preserved. There is no
|
||||
* need to zero fill here, since any trailing
|
||||
* uninititialized memory is demand-zeroed by the
|
||||
* kernel, but junk filling must be redone.
|
||||
*/
|
||||
memset(ret + oldsize, 0xa5, newsize - oldsize);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
@@ -254,6 +263,13 @@ huge_salloc(const void *ptr)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
dss_prec_t
|
||||
huge_dss_prec_get(arena_t *arena)
|
||||
{
|
||||
|
||||
return (arena_dss_prec_get(choose_arena(arena)));
|
||||
}
|
||||
|
||||
prof_ctx_t *
|
||||
huge_prof_ctx_get(const void *ptr)
|
||||
{
|
||||
|
||||
@@ -2076,7 +2076,7 @@ a0alloc(size_t size, bool zero)
|
||||
if (size <= arena_maxclass)
|
||||
return (arena_malloc(arenas[0], size, zero, false));
|
||||
else
|
||||
return (huge_malloc(size, zero));
|
||||
return (huge_malloc(size, zero, huge_dss_prec_get(arenas[0])));
|
||||
}
|
||||
|
||||
void *
|
||||
|
||||
@@ -935,9 +935,12 @@ prof_dump_maps(bool propagate_err)
|
||||
char filename[PATH_MAX + 1];
|
||||
|
||||
cassert(config_prof);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
malloc_snprintf(filename, sizeof(filename), "/proc/curproc/map");
|
||||
#else
|
||||
malloc_snprintf(filename, sizeof(filename), "/proc/%d/maps",
|
||||
(int)getpid());
|
||||
#endif
|
||||
mfd = open(filename, O_RDONLY);
|
||||
if (mfd != -1) {
|
||||
ssize_t nread;
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
* @return output
|
||||
*/
|
||||
JEMALLOC_ALWAYS_INLINE
|
||||
static vector unsigned int vec_recursion(vector unsigned int a,
|
||||
vector unsigned int vec_recursion(vector unsigned int a,
|
||||
vector unsigned int b,
|
||||
vector unsigned int c,
|
||||
vector unsigned int d) {
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
#define ASSERT_BUFSIZE 256
|
||||
|
||||
#define assert_cmp(t, a, b, cmp, neg_cmp, pri, fmt...) do { \
|
||||
t a_ = (a); \
|
||||
t b_ = (b); \
|
||||
if (!(a_ cmp b_)) { \
|
||||
p_test_fail( \
|
||||
char prefix[ASSERT_BUFSIZE]; \
|
||||
char message[ASSERT_BUFSIZE]; \
|
||||
malloc_snprintf(prefix, sizeof(prefix), \
|
||||
"%s:%s:%d: Failed assertion: " \
|
||||
"(%s) "#cmp" (%s) --> " \
|
||||
"%"pri" "#neg_cmp" %"pri": ", \
|
||||
__func__, __FILE__, __LINE__, \
|
||||
#a, #b, a_, b_, fmt); \
|
||||
#a, #b, a_, b_); \
|
||||
malloc_snprintf(message, sizeof(message), fmt); \
|
||||
p_test_fail(prefix, message); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -208,24 +214,32 @@
|
||||
bool a_ = (a); \
|
||||
bool b_ = (b); \
|
||||
if (!(a_ == b_)) { \
|
||||
p_test_fail( \
|
||||
char prefix[ASSERT_BUFSIZE]; \
|
||||
char message[ASSERT_BUFSIZE]; \
|
||||
malloc_snprintf(prefix, sizeof(prefix), \
|
||||
"%s:%s:%d: Failed assertion: " \
|
||||
"(%s) == (%s) --> %s != %s: ", \
|
||||
__func__, __FILE__, __LINE__, \
|
||||
#a, #b, a_ ? "true" : "false", \
|
||||
b_ ? "true" : "false", fmt); \
|
||||
b_ ? "true" : "false"); \
|
||||
malloc_snprintf(message, sizeof(message), fmt); \
|
||||
p_test_fail(prefix, message); \
|
||||
} \
|
||||
} while (0)
|
||||
#define assert_b_ne(a, b, fmt...) do { \
|
||||
bool a_ = (a); \
|
||||
bool b_ = (b); \
|
||||
if (!(a_ != b_)) { \
|
||||
p_test_fail( \
|
||||
char prefix[ASSERT_BUFSIZE]; \
|
||||
char message[ASSERT_BUFSIZE]; \
|
||||
malloc_snprintf(prefix, sizeof(prefix), \
|
||||
"%s:%s:%d: Failed assertion: " \
|
||||
"(%s) != (%s) --> %s == %s: ", \
|
||||
__func__, __FILE__, __LINE__, \
|
||||
#a, #b, a_ ? "true" : "false", \
|
||||
b_ ? "true" : "false", fmt); \
|
||||
b_ ? "true" : "false"); \
|
||||
malloc_snprintf(message, sizeof(message), fmt); \
|
||||
p_test_fail(prefix, message); \
|
||||
} \
|
||||
} while (0)
|
||||
#define assert_true(a, fmt...) assert_b_eq(a, true, fmt)
|
||||
@@ -233,26 +247,39 @@
|
||||
|
||||
#define assert_str_eq(a, b, fmt...) do { \
|
||||
if (strcmp((a), (b))) { \
|
||||
p_test_fail( \
|
||||
char prefix[ASSERT_BUFSIZE]; \
|
||||
char message[ASSERT_BUFSIZE]; \
|
||||
malloc_snprintf(prefix, sizeof(prefix), \
|
||||
"%s:%s:%d: Failed assertion: " \
|
||||
"(%s) same as (%s) --> " \
|
||||
"\"%s\" differs from \"%s\": ", \
|
||||
__func__, __FILE__, __LINE__, #a, #b, a, b, fmt); \
|
||||
__func__, __FILE__, __LINE__, #a, #b, a, b); \
|
||||
malloc_snprintf(message, sizeof(message), fmt); \
|
||||
p_test_fail(prefix, message); \
|
||||
} \
|
||||
} while (0)
|
||||
#define assert_str_ne(a, b, fmt...) do { \
|
||||
if (!strcmp((a), (b))) { \
|
||||
p_test_fail( \
|
||||
char prefix[ASSERT_BUFSIZE]; \
|
||||
char message[ASSERT_BUFSIZE]; \
|
||||
malloc_snprintf(prefix, sizeof(prefix), \
|
||||
"%s:%s:%d: Failed assertion: " \
|
||||
"(%s) differs from (%s) --> " \
|
||||
"\"%s\" same as \"%s\": ", \
|
||||
__func__, __FILE__, __LINE__, #a, #b, a, b, fmt); \
|
||||
__func__, __FILE__, __LINE__, #a, #b, a, b); \
|
||||
malloc_snprintf(message, sizeof(message), fmt); \
|
||||
p_test_fail(prefix, message); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define assert_not_reached(fmt...) do { \
|
||||
p_test_fail("%s:%s:%d: Unreachable code reached: ", \
|
||||
__func__, __FILE__, __LINE__, fmt); \
|
||||
char prefix[ASSERT_BUFSIZE]; \
|
||||
char message[ASSERT_BUFSIZE]; \
|
||||
malloc_snprintf(prefix, sizeof(prefix), \
|
||||
"%s:%s:%d: Unreachable code reached: ", \
|
||||
__func__, __FILE__, __LINE__); \
|
||||
malloc_snprintf(message, sizeof(message), fmt); \
|
||||
p_test_fail(prefix, message); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
@@ -299,4 +326,4 @@ void test_fail(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2));
|
||||
test_status_t p_test(test_t* t, ...);
|
||||
void p_test_init(const char *name);
|
||||
void p_test_fini(void);
|
||||
void p_test_fail(const char *format, ...);
|
||||
void p_test_fail(const char *prefix, const char *message);
|
||||
|
||||
@@ -8,7 +8,7 @@ thd_start(void *arg)
|
||||
unsigned thread_ind = (unsigned)(uintptr_t)arg;
|
||||
unsigned arena_ind;
|
||||
void *p;
|
||||
size_t rsz, sz;
|
||||
size_t sz;
|
||||
|
||||
sz = sizeof(arena_ind);
|
||||
assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0,
|
||||
@@ -27,9 +27,9 @@ thd_start(void *arg)
|
||||
sizeof(const char *)), 0, "Error in mallctlbymib()");
|
||||
}
|
||||
|
||||
assert_d_eq(allocm(&p, &rsz, 1, ALLOCM_ARENA(arena_ind)),
|
||||
ALLOCM_SUCCESS, "Unexpected allocm() error");
|
||||
dallocm(p, 0);
|
||||
p = mallocx(1, MALLOCX_ARENA(arena_ind));
|
||||
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
||||
dallocx(p, 0);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
@@ -47,10 +47,10 @@ TEST_BEGIN(test_oom_errors)
|
||||
|
||||
#if LG_SIZEOF_PTR == 3
|
||||
alignment = UINT64_C(0x4000000000000000);
|
||||
size = UINT64_C(0x8400000000000001);
|
||||
size = UINT64_C(0xc000000000000001);
|
||||
#else
|
||||
alignment = 0x40000000LU;
|
||||
size = 0x84000001LU;
|
||||
size = 0xc0000001LU;
|
||||
#endif
|
||||
set_errno(0);
|
||||
p = aligned_alloc(alignment, size);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "test/jemalloc_test.h"
|
||||
|
||||
#define CHUNK 0x400000
|
||||
/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */
|
||||
#define MAXALIGN ((size_t)0x2000000LU)
|
||||
#define MAXALIGN (((size_t)1) << 25)
|
||||
#define NITER 4
|
||||
|
||||
TEST_BEGIN(test_basic)
|
||||
@@ -39,28 +38,6 @@ TEST_BEGIN(test_basic)
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_alignment_errors)
|
||||
{
|
||||
void *p;
|
||||
size_t nsz, rsz, sz, alignment;
|
||||
|
||||
#if LG_SIZEOF_PTR == 3
|
||||
alignment = UINT64_C(0x4000000000000000);
|
||||
sz = UINT64_C(0x8400000000000001);
|
||||
#else
|
||||
alignment = 0x40000000LU;
|
||||
sz = 0x84000001LU;
|
||||
#endif
|
||||
nsz = 0;
|
||||
assert_d_eq(nallocm(&nsz, sz, ALLOCM_ALIGN(alignment)), ALLOCM_SUCCESS,
|
||||
"Unexpected nallocm() error");
|
||||
rsz = 0;
|
||||
assert_d_ne(allocm(&p, &rsz, sz, ALLOCM_ALIGN(alignment)),
|
||||
ALLOCM_SUCCESS, "Expected error for allocm(&p, %zu, %#x)",
|
||||
sz, ALLOCM_ALIGN(alignment));
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_alignment_and_size)
|
||||
{
|
||||
int r;
|
||||
@@ -126,6 +103,5 @@ main(void)
|
||||
|
||||
return (test(
|
||||
test_basic,
|
||||
test_alignment_errors,
|
||||
test_alignment_and_size));
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "test/jemalloc_test.h"
|
||||
|
||||
#define CHUNK 0x400000
|
||||
/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */
|
||||
#define MAXALIGN ((size_t)0x2000000LU)
|
||||
#define MAXALIGN (((size_t)1) << 25)
|
||||
#define NITER 4
|
||||
|
||||
TEST_BEGIN(test_basic)
|
||||
@@ -34,26 +33,6 @@ TEST_BEGIN(test_basic)
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_alignment_errors)
|
||||
{
|
||||
void *p;
|
||||
size_t nsz, sz, 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));
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_alignment_and_size)
|
||||
{
|
||||
size_t nsz, rsz, sz, alignment, total;
|
||||
@@ -114,6 +93,5 @@ main(void)
|
||||
|
||||
return (test(
|
||||
test_basic,
|
||||
test_alignment_errors,
|
||||
test_alignment_and_size));
|
||||
}
|
||||
|
||||
@@ -43,10 +43,10 @@ TEST_BEGIN(test_oom_errors)
|
||||
|
||||
#if LG_SIZEOF_PTR == 3
|
||||
alignment = UINT64_C(0x4000000000000000);
|
||||
size = UINT64_C(0x8400000000000001);
|
||||
size = UINT64_C(0xc000000000000001);
|
||||
#else
|
||||
alignment = 0x40000000LU;
|
||||
size = 0x84000001LU;
|
||||
size = 0xc0000001LU;
|
||||
#endif
|
||||
assert_d_ne(posix_memalign(&p, alignment, size), 0,
|
||||
"Expected error for posix_memalign(&p, %zu, %zu)",
|
||||
|
||||
@@ -112,7 +112,7 @@ TEST_BEGIN(test_align)
|
||||
{
|
||||
void *p, *q;
|
||||
size_t align;
|
||||
#define MAX_ALIGN (ZU(1) << 29)
|
||||
#define MAX_ALIGN (ZU(1) << 25)
|
||||
|
||||
align = ZU(1);
|
||||
p = mallocx(1, MALLOCX_ALIGN(align));
|
||||
@@ -137,7 +137,7 @@ TEST_BEGIN(test_lg_align_and_zero)
|
||||
{
|
||||
void *p, *q;
|
||||
size_t lg_align, sz;
|
||||
#define MAX_LG_ALIGN 29
|
||||
#define MAX_LG_ALIGN 25
|
||||
#define MAX_VALIDATE (ZU(1) << 22)
|
||||
|
||||
lg_align = ZU(0);
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
#include "test/jemalloc_test.h"
|
||||
#include "test/SFMT-params.h"
|
||||
|
||||
#if defined(JEMALLOC_BIG_ENDIAN) && !defined(BIG_ENDIAN64)
|
||||
#define BIG_ENDIAN64 1
|
||||
#endif
|
||||
#if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64)
|
||||
#define BIG_ENDIAN64 1
|
||||
#endif
|
||||
|
||||
@@ -86,15 +86,9 @@ p_test(test_t* t, ...)
|
||||
}
|
||||
|
||||
void
|
||||
p_test_fail(const char *format, ...)
|
||||
p_test_fail(const char *prefix, const char *message)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
malloc_vcprintf(NULL, NULL, format, ap);
|
||||
format = va_arg(ap, const char *);
|
||||
malloc_vcprintf(NULL, NULL, format, ap);
|
||||
va_end(ap);
|
||||
malloc_printf("\n");
|
||||
malloc_cprintf(NULL, NULL, "%s%s\n", prefix, message);
|
||||
test_status = test_status_fail;
|
||||
}
|
||||
|
||||
@@ -1576,7 +1576,7 @@ TEST_BEGIN(test_by_array_64)
|
||||
for (i = 0; i < BLOCK_SIZE64; i++) {
|
||||
if (i < COUNT_1) {
|
||||
assert_u64_eq(array64[i], init_by_array_64_expected[i],
|
||||
"Output mismatch for i=%d");
|
||||
"Output mismatch for i=%d", i);
|
||||
}
|
||||
r = gen_rand64(ctx);
|
||||
assert_u64_eq(r, array64[i],
|
||||
|
||||
@@ -29,7 +29,7 @@ TEST_BEGIN(test_count_insert_search_remove)
|
||||
assert_false(ckh_new(&ckh, 2, ckh_string_hash, ckh_string_keycomp),
|
||||
"Unexpected ckh_new() error");
|
||||
assert_zu_eq(ckh_count(&ckh), 0,
|
||||
"ckh_count() should return %zu, but it returned %zu", 0,
|
||||
"ckh_count() should return %zu, but it returned %zu", ZU(0),
|
||||
ckh_count(&ckh));
|
||||
|
||||
/* Insert. */
|
||||
@@ -101,11 +101,11 @@ TEST_END
|
||||
|
||||
TEST_BEGIN(test_insert_iter_remove)
|
||||
{
|
||||
#define NITEMS 1000
|
||||
#define NITEMS ZU(1000)
|
||||
ckh_t ckh;
|
||||
void **p[NITEMS];
|
||||
void *q, *r;
|
||||
unsigned i;
|
||||
size_t i;
|
||||
|
||||
assert_false(ckh_new(&ckh, 2, ckh_pointer_hash, ckh_pointer_keycomp),
|
||||
"Unexpected ckh_new() error");
|
||||
@@ -116,7 +116,7 @@ TEST_BEGIN(test_insert_iter_remove)
|
||||
}
|
||||
|
||||
for (i = 0; i < NITEMS; i++) {
|
||||
unsigned j;
|
||||
size_t j;
|
||||
|
||||
for (j = i; j < NITEMS; j++) {
|
||||
assert_false(ckh_insert(&ckh, p[j], p[j]),
|
||||
@@ -152,7 +152,7 @@ TEST_BEGIN(test_insert_iter_remove)
|
||||
|
||||
for (tabind = 0; ckh_iter(&ckh, &tabind, &q, &r) ==
|
||||
false;) {
|
||||
unsigned k;
|
||||
size_t k;
|
||||
|
||||
assert_ptr_eq(q, r, "Key and val not equal");
|
||||
|
||||
@@ -188,7 +188,7 @@ TEST_BEGIN(test_insert_iter_remove)
|
||||
}
|
||||
|
||||
assert_zu_eq(ckh_count(&ckh), 0,
|
||||
"ckh_count() should return %zu, but it returned %zu", 0,
|
||||
"ckh_count() should return %zu, but it returned %zu", ZU(0),
|
||||
ckh_count(&ckh));
|
||||
ckh_delete(&ckh);
|
||||
#undef NITEMS
|
||||
|
||||
@@ -122,9 +122,15 @@ hash_variant_verify(hash_variant_t variant)
|
||||
(final[3] << 24);
|
||||
|
||||
switch (variant) {
|
||||
#ifdef JEMALLOC_BIG_ENDIAN
|
||||
case hash_variant_x86_32: expected = 0x6213303eU; break;
|
||||
case hash_variant_x86_128: expected = 0x266820caU; break;
|
||||
case hash_variant_x64_128: expected = 0xcc622b6fU; break;
|
||||
#else
|
||||
case hash_variant_x86_32: expected = 0xb0f57ee3U; break;
|
||||
case hash_variant_x86_128: expected = 0xb3ece62aU; break;
|
||||
case hash_variant_x64_128: expected = 0x6384ba69U; break;
|
||||
#endif
|
||||
default: not_reached();
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ test_junk(size_t sz_min, size_t sz_max)
|
||||
if (sz_prev > 0) {
|
||||
assert_c_eq(s[0], 'a',
|
||||
"Previously allocated byte %zu/%zu is corrupted",
|
||||
0, sz_prev);
|
||||
ZU(0), sz_prev);
|
||||
assert_c_eq(s[sz_prev-1], 'a',
|
||||
"Previously allocated byte %zu/%zu is corrupted",
|
||||
sz_prev-1, sz_prev);
|
||||
@@ -92,9 +92,12 @@ test_junk(size_t sz_min, size_t sz_max)
|
||||
s = (char *)rallocx(s, sz+1, 0);
|
||||
assert_ptr_not_null((void *)s,
|
||||
"Unexpected rallocx() failure");
|
||||
assert_ptr_eq(most_recently_junked, junked,
|
||||
"Expected region of size %zu to be junk-filled",
|
||||
sz);
|
||||
if (!config_mremap || sz+1 <= arena_maxclass) {
|
||||
assert_ptr_eq(most_recently_junked, junked,
|
||||
"Expected region of size %zu to be "
|
||||
"junk-filled",
|
||||
sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
#include "test/jemalloc_test.h"
|
||||
|
||||
#define NTHREADS 4
|
||||
#define NALLOCS_PER_THREAD 50
|
||||
#define DUMP_INTERVAL 1
|
||||
#define BT_COUNT_CHECK_INTERVAL 5
|
||||
#include "prof_accum.h"
|
||||
|
||||
#ifdef JEMALLOC_PROF
|
||||
const char *malloc_conf =
|
||||
@@ -21,37 +16,6 @@ prof_dump_open_intercept(bool propagate_err, const char *filename)
|
||||
return (fd);
|
||||
}
|
||||
|
||||
#define alloc_n_proto(n) \
|
||||
static void *alloc_##n(unsigned bits);
|
||||
|
||||
#define alloc_n_gen(n) \
|
||||
static void * \
|
||||
alloc_##n(unsigned bits) \
|
||||
{ \
|
||||
void *p; \
|
||||
\
|
||||
if (bits == 0) \
|
||||
p = mallocx(1, 0); \
|
||||
else { \
|
||||
switch (bits & 0x1U) { \
|
||||
case 0: \
|
||||
p = alloc_0(bits >> 1); \
|
||||
break; \
|
||||
case 1: \
|
||||
p = alloc_1(bits >> 1); \
|
||||
break; \
|
||||
default: not_reached(); \
|
||||
} \
|
||||
} \
|
||||
/* Intentionally sabotage tail call optimization. */ \
|
||||
assert_ptr_not_null(p, "Unexpected mallocx() failure"); \
|
||||
return (p); \
|
||||
}
|
||||
alloc_n_proto(0)
|
||||
alloc_n_proto(1)
|
||||
alloc_n_gen(0)
|
||||
alloc_n_gen(1)
|
||||
|
||||
static void *
|
||||
alloc_from_permuted_backtrace(unsigned thd_ind, unsigned iteration)
|
||||
{
|
||||
|
||||
35
test/unit/prof_accum.h
Normal file
35
test/unit/prof_accum.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "test/jemalloc_test.h"
|
||||
|
||||
#define NTHREADS 4
|
||||
#define NALLOCS_PER_THREAD 50
|
||||
#define DUMP_INTERVAL 1
|
||||
#define BT_COUNT_CHECK_INTERVAL 5
|
||||
|
||||
#define alloc_n_proto(n) \
|
||||
void *alloc_##n(unsigned bits);
|
||||
alloc_n_proto(0)
|
||||
alloc_n_proto(1)
|
||||
|
||||
#define alloc_n_gen(n) \
|
||||
void * \
|
||||
alloc_##n(unsigned bits) \
|
||||
{ \
|
||||
void *p; \
|
||||
\
|
||||
if (bits == 0) \
|
||||
p = mallocx(1, 0); \
|
||||
else { \
|
||||
switch (bits & 0x1U) { \
|
||||
case 0: \
|
||||
p = (alloc_0(bits >> 1)); \
|
||||
break; \
|
||||
case 1: \
|
||||
p = (alloc_1(bits >> 1)); \
|
||||
break; \
|
||||
default: not_reached(); \
|
||||
} \
|
||||
} \
|
||||
/* Intentionally sabotage tail call optimization. */ \
|
||||
assert_ptr_not_null(p, "Unexpected mallocx() failure"); \
|
||||
return (p); \
|
||||
}
|
||||
3
test/unit/prof_accum_a.c
Normal file
3
test/unit/prof_accum_a.c
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "prof_accum.h"
|
||||
|
||||
alloc_n_gen(0)
|
||||
3
test/unit/prof_accum_b.c
Normal file
3
test/unit/prof_accum_b.c
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "prof_accum.h"
|
||||
|
||||
alloc_n_gen(1)
|
||||
@@ -21,7 +21,7 @@ quarantine_clear(void)
|
||||
|
||||
TEST_BEGIN(test_quarantine)
|
||||
{
|
||||
#define SZ 256
|
||||
#define SZ ZU(256)
|
||||
#define NQUARANTINED (QUARANTINE_SIZE/SZ)
|
||||
void *quarantined[NQUARANTINED+1];
|
||||
size_t i, j;
|
||||
|
||||
@@ -48,8 +48,9 @@ TEST_BEGIN(test_rtree_bits)
|
||||
assert_u_eq(rtree_get(rtree, keys[k]), 1,
|
||||
"rtree_get() should return previously set "
|
||||
"value and ignore insignificant key bits; "
|
||||
"i=%u, j=%u, k=%u, set key=%#x, "
|
||||
"get key=%#x", i, j, k, keys[j], keys[k]);
|
||||
"i=%u, j=%u, k=%u, set key=%#"PRIxPTR", "
|
||||
"get key=%#"PRIxPTR, i, j, k, keys[j],
|
||||
keys[k]);
|
||||
}
|
||||
assert_u_eq(rtree_get(rtree,
|
||||
(((uintptr_t)1) << (sizeof(uintptr_t)*8-i))), 0,
|
||||
|
||||
@@ -31,21 +31,25 @@ TEST_END
|
||||
|
||||
TEST_BEGIN(test_stats_chunks)
|
||||
{
|
||||
size_t current, total, high;
|
||||
size_t sz = sizeof(size_t);
|
||||
size_t current, high;
|
||||
uint64_t total;
|
||||
size_t sz;
|
||||
int expected = config_stats ? 0 : ENOENT;
|
||||
|
||||
sz = sizeof(size_t);
|
||||
assert_d_eq(mallctl("stats.chunks.current", ¤t, &sz, NULL, 0),
|
||||
expected, "Unexpected mallctl() result");
|
||||
sz = sizeof(uint64_t);
|
||||
assert_d_eq(mallctl("stats.chunks.total", &total, &sz, NULL, 0),
|
||||
expected, "Unexpected mallctl() result");
|
||||
sz = sizeof(size_t);
|
||||
assert_d_eq(mallctl("stats.chunks.high", &high, &sz, NULL, 0), expected,
|
||||
"Unexpected mallctl() result");
|
||||
|
||||
if (config_stats) {
|
||||
assert_zu_le(current, high,
|
||||
"current should be no larger than high");
|
||||
assert_zu_le(high, total,
|
||||
assert_u64_le((uint64_t)high, total,
|
||||
"high should be no larger than total");
|
||||
}
|
||||
}
|
||||
@@ -247,9 +251,9 @@ TEST_BEGIN(test_stats_arenas_bins)
|
||||
{
|
||||
unsigned arena;
|
||||
void *p;
|
||||
size_t sz, allocated;
|
||||
size_t sz, allocated, curruns;
|
||||
uint64_t epoch, nmalloc, ndalloc, nrequests, nfills, nflushes;
|
||||
uint64_t nruns, nreruns, curruns;
|
||||
uint64_t nruns, nreruns;
|
||||
int expected = config_stats ? 0 : ENOENT;
|
||||
|
||||
arena = 0;
|
||||
@@ -287,6 +291,7 @@ TEST_BEGIN(test_stats_arenas_bins)
|
||||
NULL, 0), expected, "Unexpected mallctl() result");
|
||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.nreruns", &nreruns, &sz,
|
||||
NULL, 0), expected, "Unexpected mallctl() result");
|
||||
sz = sizeof(size_t);
|
||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.curruns", &curruns, &sz,
|
||||
NULL, 0), expected, "Unexpected mallctl() result");
|
||||
|
||||
@@ -307,7 +312,7 @@ TEST_BEGIN(test_stats_arenas_bins)
|
||||
}
|
||||
assert_u64_gt(nruns, 0,
|
||||
"At least one run should have been allocated");
|
||||
assert_u64_gt(curruns, 0,
|
||||
assert_zu_gt(curruns, 0,
|
||||
"At least one run should be currently allocated");
|
||||
}
|
||||
|
||||
@@ -319,8 +324,8 @@ TEST_BEGIN(test_stats_arenas_lruns)
|
||||
{
|
||||
unsigned arena;
|
||||
void *p;
|
||||
uint64_t epoch, nmalloc, ndalloc, nrequests, curruns;
|
||||
size_t sz = sizeof(uint64_t);
|
||||
uint64_t epoch, nmalloc, ndalloc, nrequests;
|
||||
size_t curruns, sz;
|
||||
int expected = config_stats ? 0 : ENOENT;
|
||||
|
||||
arena = 0;
|
||||
@@ -333,12 +338,14 @@ TEST_BEGIN(test_stats_arenas_lruns)
|
||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
|
||||
"Unexpected mallctl() failure");
|
||||
|
||||
sz = sizeof(uint64_t);
|
||||
assert_d_eq(mallctl("stats.arenas.0.lruns.0.nmalloc", &nmalloc, &sz,
|
||||
NULL, 0), expected, "Unexpected mallctl() result");
|
||||
assert_d_eq(mallctl("stats.arenas.0.lruns.0.ndalloc", &ndalloc, &sz,
|
||||
NULL, 0), expected, "Unexpected mallctl() result");
|
||||
assert_d_eq(mallctl("stats.arenas.0.lruns.0.nrequests", &nrequests, &sz,
|
||||
NULL, 0), expected, "Unexpected mallctl() result");
|
||||
sz = sizeof(size_t);
|
||||
assert_d_eq(mallctl("stats.arenas.0.lruns.0.curruns", &curruns, &sz,
|
||||
NULL, 0), expected, "Unexpected mallctl() result");
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ test_zero(size_t sz_min, size_t sz_max)
|
||||
if (sz_prev > 0) {
|
||||
assert_c_eq(s[0], 'a',
|
||||
"Previously allocated byte %zu/%zu is corrupted",
|
||||
0, sz_prev);
|
||||
ZU(0), sz_prev);
|
||||
assert_c_eq(s[sz_prev-1], 'a',
|
||||
"Previously allocated byte %zu/%zu is corrupted",
|
||||
sz_prev-1, sz_prev);
|
||||
|
||||
Reference in New Issue
Block a user