mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-22 20:53:07 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e27d134efc | ||
|
|
6e56e5ec6a | ||
|
|
af5d6987f8 | ||
|
|
655f04a5a4 | ||
|
|
9dcad2dfd1 | ||
|
|
6369286f83 | ||
|
|
a73ebd946a | ||
|
|
ada55b2e92 | ||
|
|
31bfb3e7b0 | ||
|
|
f256680f87 | ||
|
|
dbd3832d20 | ||
|
|
10e4523094 | ||
|
|
624f2f3cc9 | ||
|
|
8ad0eacfb3 | ||
|
|
2a6f2af6e4 | ||
|
|
2b769797ce | ||
|
|
50ac670d09 | ||
|
|
1c4b088b08 | ||
|
|
0e8d3d2cb9 | ||
|
|
ecf229a39f | ||
|
|
cfdc8cfbd6 | ||
|
|
aee7fd2b70 | ||
|
|
fc4dcfa2f5 | ||
|
|
1f17bd9395 | ||
|
|
0a36622dd1 | ||
|
|
53806fef53 | ||
|
|
b04a940ee5 | ||
|
|
d4bab21756 | ||
|
|
b059a534f7 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -3,6 +3,10 @@
|
||||
/jemalloc/config.log
|
||||
/jemalloc/config.status
|
||||
/jemalloc/configure
|
||||
/jemalloc/doc/html.xsl
|
||||
/jemalloc/doc/manpages.xsl
|
||||
/jemalloc/doc/jemalloc.xml
|
||||
/jemalloc/doc/jemalloc.html
|
||||
/jemalloc/doc/jemalloc.3
|
||||
/jemalloc/lib/
|
||||
/jemalloc/Makefile
|
||||
@@ -13,4 +17,7 @@
|
||||
/jemalloc/src/*.[od]
|
||||
/jemalloc/test/*.[od]
|
||||
/jemalloc/test/*.out
|
||||
/jemalloc/test/[a-z]*
|
||||
!/jemalloc/test/*.c
|
||||
!/jemalloc/test/*.exp
|
||||
/jemalloc/VERSION
|
||||
|
||||
@@ -6,42 +6,81 @@ found in the git revision history:
|
||||
http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git
|
||||
git://canonware.com/jemalloc.git
|
||||
|
||||
* 2.0.0
|
||||
* 2.1.2 (March 2, 2011)
|
||||
|
||||
Bug fixes:
|
||||
- Fix "thread.{de,}allocatedp" mallctl for OS X.
|
||||
- Add missing jemalloc.a to build system.
|
||||
|
||||
* 2.1.1 (January 31, 2011)
|
||||
|
||||
Bug fixes:
|
||||
- Fix aligned huge reallocation (affected allocm()).
|
||||
- Fix the ALLOCM_LG_ALIGN macro definition.
|
||||
- Fix a heap dumping deadlock.
|
||||
- Fix a "thread.arena" mallctl bug.
|
||||
|
||||
* 2.1.0 (December 3, 2010)
|
||||
|
||||
This version incorporates some optimizations that can't quite be considered
|
||||
bug fixes.
|
||||
|
||||
New features:
|
||||
- Use Linux's mremap(2) for huge object reallocation when possible.
|
||||
- Avoid locking in mallctl*() when possible.
|
||||
- Add the "thread.[de]allocatedp" mallctl's.
|
||||
- Convert the manual page source from roff to DocBook, and generate both roff
|
||||
and HTML manuals.
|
||||
|
||||
Bug fixes:
|
||||
- Fix a crash due to incorrect bootstrap ordering. This only impacted
|
||||
--enable-debug --enable-dss configurations.
|
||||
- Fix a minor statistics bug for mallctl("swap.avail", ...).
|
||||
|
||||
* 2.0.1 (October 29, 2010)
|
||||
|
||||
Bug fixes:
|
||||
- Fix a race condition in heap profiling that could cause undefined behavior
|
||||
if "opt.prof_accum" were disabled.
|
||||
- Add missing mutex unlocks for some OOM error paths in the heap profiling
|
||||
code.
|
||||
- Fix a compilation error for non-C99 builds.
|
||||
|
||||
* 2.0.0 (October 24, 2010)
|
||||
|
||||
This version focuses on the experimental *allocm() API, and on improved
|
||||
run-time configuration/introspection. Nonetheless, numerous performance
|
||||
improvements are also included.
|
||||
|
||||
New features:
|
||||
- Implement the experimental {,r,s,d}allocm() API, which provides a superset
|
||||
of the functionality available via malloc(), calloc(), posix_memalign(),
|
||||
realloc(), malloc_usable_size(), and free(). These functions can be used
|
||||
to allocate/reallocate aligned zeroed memory, ask for optional extra
|
||||
memory during reallocation, prevent object movement during reallocation,
|
||||
etc.
|
||||
- Replace JEMALLOC_OPTIONS/JEMALLOC_PROF_PREFIX with MALLOC_CONF, which is
|
||||
more human-readable, and more flexible. For example:
|
||||
JEMALLOC_OPTIONS=AJP
|
||||
is now:
|
||||
MALLOC_CONF=abort:true,fill:true,stats_print:true
|
||||
- Port to Apple OS X. Sponsored by Mozilla.
|
||||
- Make it possible for the application to control thread-->arena mappings
|
||||
via the "thread.arena" mallctl.
|
||||
- Add compile-time support for all TLS-related functionality via pthreads
|
||||
TSD. This is mainly of interest for OS X, which does not support TLS, but
|
||||
has a TSD implementation with similar performance.
|
||||
- Override memalign() and valloc() if they are provided by the system.
|
||||
- Add the "arenas.purge" mallctl, which can be used to synchronously purge
|
||||
all dirty unused pages.
|
||||
- Make cumulative heap profiling data optional, so that it is possible to
|
||||
limit the amount of memory consumed by heap profiling data structures.
|
||||
- Add per thread allocation counters that can be accessed via the
|
||||
"thread.allocated" and "thread.deallocated" mallctls.
|
||||
- Implement the experimental {,r,s,d}allocm() API, which provides a superset
|
||||
of the functionality available via malloc(), calloc(), posix_memalign(),
|
||||
realloc(), malloc_usable_size(), and free(). These functions can be used to
|
||||
allocate/reallocate aligned zeroed memory, ask for optional extra memory
|
||||
during reallocation, prevent object movement during reallocation, etc.
|
||||
- Replace JEMALLOC_OPTIONS/JEMALLOC_PROF_PREFIX with MALLOC_CONF, which is
|
||||
more human-readable, and more flexible. For example:
|
||||
JEMALLOC_OPTIONS=AJP
|
||||
is now:
|
||||
MALLOC_CONF=abort:true,fill:true,stats_print:true
|
||||
- Port to Apple OS X. Sponsored by Mozilla.
|
||||
- Make it possible for the application to control thread-->arena mappings via
|
||||
the "thread.arena" mallctl.
|
||||
- Add compile-time support for all TLS-related functionality via pthreads TSD.
|
||||
This is mainly of interest for OS X, which does not support TLS, but has a
|
||||
TSD implementation with similar performance.
|
||||
- Override memalign() and valloc() if they are provided by the system.
|
||||
- Add the "arenas.purge" mallctl, which can be used to synchronously purge all
|
||||
dirty unused pages.
|
||||
- Make cumulative heap profiling data optional, so that it is possible to
|
||||
limit the amount of memory consumed by heap profiling data structures.
|
||||
- Add per thread allocation counters that can be accessed via the
|
||||
"thread.allocated" and "thread.deallocated" mallctls.
|
||||
|
||||
Incompatible changes:
|
||||
- Remove JEMALLOC_OPTIONS and malloc_options (see MALLOC_CONF above).
|
||||
- Increase default backtrace depth from 4 to 128 for heap profiling.
|
||||
- Disable interval-based profile dumps by default.
|
||||
- Remove JEMALLOC_OPTIONS and malloc_options (see MALLOC_CONF above).
|
||||
- Increase default backtrace depth from 4 to 128 for heap profiling.
|
||||
- Disable interval-based profile dumps by default.
|
||||
|
||||
Bug fixes:
|
||||
- Remove bad assertions in fork handler functions. These assertions could
|
||||
@@ -59,7 +98,7 @@ found in the git revision history:
|
||||
- Fix a heap profiling bug due to sometimes losing track of requested object
|
||||
size for sampled objects.
|
||||
|
||||
* 1.0.3
|
||||
* 1.0.3 (August 12, 2010)
|
||||
|
||||
Bug fixes:
|
||||
- Fix the libunwind-based implementation of stack backtracing (used for heap
|
||||
@@ -68,7 +107,7 @@ found in the git revision history:
|
||||
threads raced to initialize malloc, some of them could end up permanently
|
||||
blocked.
|
||||
|
||||
* 1.0.2
|
||||
* 1.0.2 (May 11, 2010)
|
||||
|
||||
Bug fixes:
|
||||
- Fix junk filling of large objects, which could cause memory corruption.
|
||||
@@ -76,7 +115,7 @@ found in the git revision history:
|
||||
memory limits could cause swap file configuration to fail. Contributed by
|
||||
Jordan DeLong.
|
||||
|
||||
* 1.0.1
|
||||
* 1.0.1 (April 14, 2010)
|
||||
|
||||
Bug fixes:
|
||||
- Fix compilation when --enable-fill is specified.
|
||||
@@ -85,7 +124,7 @@ found in the git revision history:
|
||||
- Fix dirty page purging race conditions that could cause crashes.
|
||||
- Fix crash in tcache flushing code during thread destruction.
|
||||
|
||||
* 1.0.0
|
||||
* 1.0.0 (April 11, 2010)
|
||||
|
||||
This release focuses on speed and run-time introspection. Numerous
|
||||
algorithmic improvements make this release substantially faster than its
|
||||
@@ -121,7 +160,7 @@ found in the git revision history:
|
||||
- Fix a chunk leak. The leaked chunks were never touched, so this impacted
|
||||
virtual memory usage, but not physical memory usage.
|
||||
|
||||
* linux_20080828a, linux_20080827a
|
||||
* linux_2008082[78]a (August 27/28, 2008)
|
||||
|
||||
These snapshot releases are the simple result of incorporating Linux-specific
|
||||
support into the FreeBSD malloc sources.
|
||||
|
||||
@@ -28,7 +28,7 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
|
||||
--with-jemalloc-prefix=<prefix>
|
||||
Prefix all public APIs with <prefix>. For example, if <prefix> is
|
||||
"prefix_", the API changes like the following occur:
|
||||
"prefix_", API changes like the following occur:
|
||||
|
||||
malloc() --> prefix_malloc()
|
||||
malloc_conf --> prefix_malloc_conf
|
||||
@@ -48,9 +48,9 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
example, libjemalloc.so.0 becomes libjemalloc<suffix>.so.0.
|
||||
|
||||
--enable-cc-silence
|
||||
Enable code that silences unuseful compiler warnings. This is helpful when
|
||||
trying to tell serious warnings from those due to compiler limitations, but
|
||||
it potentially incurs a performance penalty.
|
||||
Enable code that silences non-useful compiler warnings. This is helpful
|
||||
when trying to tell serious warnings from those due to compiler
|
||||
limitations, but it potentially incurs a performance penalty.
|
||||
|
||||
--enable-debug
|
||||
Enable assertions and validation code. This incurs a substantial
|
||||
@@ -62,7 +62,7 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
|
||||
--enable-prof
|
||||
Enable heap profiling and leak detection functionality. See the "opt.prof"
|
||||
option documention for usage details.
|
||||
option documentation for usage details.
|
||||
|
||||
--disable-prof-libgcc
|
||||
Disable the use of libgcc's backtracing functionality. Ordinarily, libgcc's
|
||||
@@ -89,7 +89,7 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
--disable-tcache
|
||||
Disable thread-specific caches for small objects. Objects are cached and
|
||||
released in bulk, thus reducing the total number of mutex operations. See
|
||||
the "opt.tcache" option for suage details.
|
||||
the "opt.tcache" option for usage details.
|
||||
|
||||
--enable-swap
|
||||
Enable mmap()ed swap file support. When this feature is built in, it is
|
||||
@@ -132,8 +132,11 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
--disable-tls
|
||||
Disable thread-local storage (TLS), which allows for fast access to
|
||||
thread-local variables via the __thread keyword. If TLS is available,
|
||||
jemalloc uses it for several purposes. Note that disabling TLS implies
|
||||
--disable-tcache.
|
||||
jemalloc uses it for several purposes.
|
||||
|
||||
--with-xslroot=<path>
|
||||
Specify where to find DocBook XSL stylesheets when building the
|
||||
documentation.
|
||||
|
||||
The following environment variables (not a definitive list) impact configure's
|
||||
behavior:
|
||||
@@ -172,7 +175,7 @@ To install only parts of jemalloc, use the following targets:
|
||||
install_bin
|
||||
install_include
|
||||
install_lib
|
||||
install_man
|
||||
install_doc
|
||||
|
||||
To clean up build results to varying degrees, use the following make targets:
|
||||
|
||||
@@ -195,8 +198,8 @@ MANDIR="?"
|
||||
Use this as the installation prefix for man pages.
|
||||
|
||||
DESTDIR="?"
|
||||
Prepend DESTDIR to INCLUDEDIR, LIBDIR, and MANDIR. This is useful when
|
||||
installing to a different path than was specified via --prefix.
|
||||
Prepend DESTDIR to INCLUDEDIR, LIBDIR, DATADIR, and MANDIR. This is useful
|
||||
when installing to a different path than was specified via --prefix.
|
||||
|
||||
CC="?"
|
||||
Use this to invoke the C compiler.
|
||||
@@ -232,11 +235,12 @@ directory, issue configuration and build commands:
|
||||
|
||||
=== Documentation ==============================================================
|
||||
|
||||
The manual page that the configure script generates can be manually formatted
|
||||
The manual page is generated in both html and roff formats. Any web browser
|
||||
can be used to view the html manual. The roff manual page can be formatted
|
||||
prior to installation via any of the following commands:
|
||||
|
||||
nroff -man -man-ext -t doc/jemalloc.3
|
||||
nroff -man -t doc/jemalloc.3
|
||||
|
||||
groff -man -man-ext -t -Tps doc/jemalloc.3 | ps2pdf - doc/jemalloc.3.pdf
|
||||
groff -man -t -Tps doc/jemalloc.3 | ps2pdf - doc/jemalloc.3.pdf
|
||||
|
||||
(cd doc; groff -man -man-ext -t -Thtml jemalloc.3 > jemalloc.3.html)
|
||||
|
||||
@@ -15,11 +15,12 @@ DESTDIR =
|
||||
BINDIR := $(DESTDIR)@BINDIR@
|
||||
INCLUDEDIR := $(DESTDIR)@INCLUDEDIR@
|
||||
LIBDIR := $(DESTDIR)@LIBDIR@
|
||||
DATADIR := $(DESTDIR)@DATADIR@
|
||||
MANDIR := $(DESTDIR)@MANDIR@
|
||||
|
||||
# Build parameters.
|
||||
CPPFLAGS := @CPPFLAGS@ -I@srcroot@include -I@objroot@include
|
||||
CFLAGS := @CFLAGS@ -fPIC -DPIC
|
||||
CFLAGS := @CFLAGS@
|
||||
ifeq (macho, @abi@)
|
||||
CFLAGS += -dynamic
|
||||
endif
|
||||
@@ -54,18 +55,40 @@ CSRCS := @srcroot@src/jemalloc.c @srcroot@src/arena.c @srcroot@src/base.c \
|
||||
ifeq (macho, @abi@)
|
||||
CSRCS += @srcroot@src/zone.c
|
||||
endif
|
||||
STATIC_LIBS := @objroot@lib/libjemalloc@install_suffix@.a
|
||||
DSOS := @objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) \
|
||||
@objroot@lib/libjemalloc@install_suffix@.$(SO) \
|
||||
@objroot@lib/libjemalloc@install_suffix@_pic.a
|
||||
MAN3 := @objroot@doc/jemalloc@install_suffix@.3
|
||||
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/allocm.c \
|
||||
@srcroot@test/posix_memalign.c \
|
||||
@srcroot@test/mremap.c @srcroot@test/posix_memalign.c \
|
||||
@srcroot@test/rallocm.c @srcroot@test/thread_arena.c
|
||||
|
||||
.PHONY: all dist install check clean distclean relclean
|
||||
.PHONY: all dist doc_html doc_man doc
|
||||
.PHONY: install_bin install_include install_lib
|
||||
.PHONY: install_html install_man install_doc install
|
||||
.PHONY: tests check clean distclean relclean
|
||||
|
||||
.SECONDARY : $(CTESTS:@srcroot@%.c=@objroot@%.o)
|
||||
|
||||
# Default target.
|
||||
all: $(DSOS)
|
||||
all: $(DSOS) $(STATIC_LIBS)
|
||||
|
||||
dist: doc
|
||||
|
||||
@srcroot@doc/%.html : @objroot@doc/%.xml @srcroot@doc/stylesheet.xsl @objroot@doc/html.xsl
|
||||
@XSLTPROC@ -o $@ @objroot@doc/html.xsl $<
|
||||
|
||||
@srcroot@doc/%.3 : @objroot@doc/%.xml @srcroot@doc/stylesheet.xsl @objroot@doc/manpages.xsl
|
||||
@XSLTPROC@ -o $@ @objroot@doc/manpages.xsl $<
|
||||
|
||||
doc_html: $(DOCS_HTML)
|
||||
doc_man: $(DOCS_MAN3)
|
||||
doc: $(DOCS)
|
||||
|
||||
#
|
||||
# Include generated dependency files.
|
||||
@@ -77,15 +100,24 @@ all: $(DSOS)
|
||||
$(CC) $(CFLAGS) -c $(CPPFLAGS) -o $@ $<
|
||||
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"
|
||||
|
||||
@objroot@src/%.pic.o: @srcroot@src/%.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) -fPIC -DPIC -c $(CPPFLAGS) -o $@ $<
|
||||
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"
|
||||
|
||||
%.$(SO) : %.$(SO).$(REV)
|
||||
@mkdir -p $(@D)
|
||||
ln -sf $(<F) $@
|
||||
|
||||
@objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) : $(CSRCS:@srcroot@%.c=@objroot@%.o)
|
||||
@objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) : $(CSRCS:@srcroot@%.c=@objroot@%.pic.o)
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -shared -Wl,-$(WL_SONAME),$(@F) $(RPATH_EXTRA:%=@RPATH@%) -o $@ $+ $(LDFLAGS) $(LIBS)
|
||||
|
||||
@objroot@lib/libjemalloc@install_suffix@_pic.a : $(CSRCS:@srcroot@%.c=@objroot@%.o)
|
||||
@objroot@lib/libjemalloc@install_suffix@_pic.a : $(CSRCS:@srcroot@%.c=@objroot@%.pic.o)
|
||||
@mkdir -p $(@D)
|
||||
ar crus $@ $+
|
||||
|
||||
@objroot@lib/libjemalloc@install_suffix@.a : $(CSRCS:@srcroot@%.c=@objroot@%.o)
|
||||
@mkdir -p $(@D)
|
||||
ar crus $@ $+
|
||||
|
||||
@@ -117,20 +149,30 @@ install_include:
|
||||
install -m 644 $$h $(INCLUDEDIR)/jemalloc; \
|
||||
done
|
||||
|
||||
install_lib: $(DSOS)
|
||||
install_lib: $(DSOS) $(STATIC_LIBS)
|
||||
install -d $(LIBDIR)
|
||||
install -m 755 @objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) $(LIBDIR)
|
||||
ln -sf libjemalloc@install_suffix@.$(SO).$(REV) $(LIBDIR)/libjemalloc@install_suffix@.$(SO)
|
||||
install -m 755 @objroot@lib/libjemalloc@install_suffix@_pic.a $(LIBDIR)
|
||||
install -m 755 @objroot@lib/libjemalloc@install_suffix@.a $(LIBDIR)
|
||||
|
||||
install_html:
|
||||
install -d $(DATADIR)/doc/jemalloc@install_suffix@
|
||||
@for d in $(DOCS_HTML); do \
|
||||
echo "install -m 644 $$d $(DATADIR)/doc/jemalloc@install_suffix@"; \
|
||||
install -m 644 $$d $(DATADIR)/doc/jemalloc@install_suffix@; \
|
||||
done
|
||||
|
||||
install_man:
|
||||
install -d $(MANDIR)/man3
|
||||
@for m in $(MAN3); do \
|
||||
echo "install -m 644 $$m $(MANDIR)/man3"; \
|
||||
install -m 644 $$m $(MANDIR)/man3; \
|
||||
@for d in $(DOCS_MAN3); do \
|
||||
echo "install -m 644 $$d $(MANDIR)/man3"; \
|
||||
install -m 644 $$d $(MANDIR)/man3; \
|
||||
done
|
||||
|
||||
install: install_bin install_include install_lib install_man
|
||||
install_doc: install_html install_man
|
||||
|
||||
install: install_bin install_include install_lib install_doc
|
||||
|
||||
tests: $(CTESTS:@srcroot@%.c=@objroot@%)
|
||||
|
||||
@@ -164,12 +206,14 @@ check: tests
|
||||
|
||||
clean:
|
||||
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.o)
|
||||
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.pic.o)
|
||||
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.d)
|
||||
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.pic.d)
|
||||
rm -f $(CTESTS:@srcroot@%.c=@objroot@%)
|
||||
rm -f $(CTESTS:@srcroot@%.c=@objroot@%.o)
|
||||
rm -f $(CTESTS:@srcroot@%.c=@objroot@%.d)
|
||||
rm -f $(CTESTS:@srcroot@%.c=@objroot@%.out)
|
||||
rm -f $(DSOS)
|
||||
rm -f $(DSOS) $(STATIC_LIBS)
|
||||
|
||||
distclean: clean
|
||||
rm -rf @objroot@autom4te.cache
|
||||
@@ -182,6 +226,8 @@ distclean: clean
|
||||
relclean: distclean
|
||||
rm -f @objroot@configure
|
||||
rm -f @srcroot@VERSION
|
||||
rm -f $(DOCS_HTML)
|
||||
rm -f $(DOCS_MAN3)
|
||||
|
||||
#===============================================================================
|
||||
# Re-configuration rules.
|
||||
|
||||
@@ -80,6 +80,19 @@ MANDIR=`eval echo $mandir`
|
||||
MANDIR=`eval echo $MANDIR`
|
||||
AC_SUBST([MANDIR])
|
||||
|
||||
dnl Support for building documentation.
|
||||
AC_PATH_PROG([XSLTPROC], [xsltproc], , [$PATH])
|
||||
AC_ARG_WITH([xslroot],
|
||||
[AS_HELP_STRING([--with-xslroot=<path>], [XSL stylesheet root path])],
|
||||
if test "x$with_xslroot" = "xno" ; then
|
||||
XSLROOT="/usr/share/xml/docbook/stylesheet/docbook-xsl"
|
||||
else
|
||||
XSLROOT="${with_xslroot}"
|
||||
fi,
|
||||
XSLROOT="/usr/share/xml/docbook/stylesheet/docbook-xsl"
|
||||
)
|
||||
AC_SUBST([XSLROOT])
|
||||
|
||||
dnl If CFLAGS isn't defined, set CFLAGS to something reasonable. Otherwise,
|
||||
dnl just prevent autoconf from molesting CFLAGS.
|
||||
CFLAGS=$CFLAGS
|
||||
@@ -214,6 +227,16 @@ esac
|
||||
AC_SUBST([abi])
|
||||
AC_SUBST([RPATH])
|
||||
|
||||
JE_COMPILABLE([mremap(...MREMAP_FIXED...)], [
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/mman.h>
|
||||
], [
|
||||
void *p = mremap((void *)0, 0, 0, MREMAP_MAYMOVE|MREMAP_FIXED, (void *)0);
|
||||
], [mremap_fixed])
|
||||
if test "x${mremap_fixed}" = "xyes" ; then
|
||||
AC_DEFINE([JEMALLOC_MREMAP_FIXED])
|
||||
fi
|
||||
|
||||
dnl Support optional additions to rpath.
|
||||
AC_ARG_WITH([rpath],
|
||||
[AS_HELP_STRING([--with-rpath=<rpath>], [Colon-separated rpath (ELF systems only)])],
|
||||
@@ -275,17 +298,26 @@ AC_ARG_WITH([install_suffix],
|
||||
install_suffix="$INSTALL_SUFFIX"
|
||||
AC_SUBST([install_suffix])
|
||||
|
||||
cfgoutputs_in="${srcroot}Makefile.in ${srcroot}doc/jemalloc.3.in"
|
||||
cfgoutputs_in="${srcroot}Makefile.in"
|
||||
cfgoutputs_in="${cfgoutputs_in} ${srcroot}doc/html.xsl.in"
|
||||
cfgoutputs_in="${cfgoutputs_in} ${srcroot}doc/manpages.xsl.in"
|
||||
cfgoutputs_in="${cfgoutputs_in} ${srcroot}doc/jemalloc.xml.in"
|
||||
cfgoutputs_in="${cfgoutputs_in} ${srcroot}include/jemalloc/jemalloc.h.in"
|
||||
cfgoutputs_in="${cfgoutputs_in} ${srcroot}include/jemalloc/internal/jemalloc_internal.h.in"
|
||||
cfgoutputs_in="${cfgoutputs_in} ${srcroot}test/jemalloc_test.h.in"
|
||||
|
||||
cfgoutputs_out="Makefile doc/jemalloc${install_suffix}.3"
|
||||
cfgoutputs_out="Makefile"
|
||||
cfgoutputs_out="${cfgoutputs_out} doc/html.xsl"
|
||||
cfgoutputs_out="${cfgoutputs_out} doc/manpages.xsl"
|
||||
cfgoutputs_out="${cfgoutputs_out} doc/jemalloc${install_suffix}.xml"
|
||||
cfgoutputs_out="${cfgoutputs_out} include/jemalloc/jemalloc${install_suffix}.h"
|
||||
cfgoutputs_out="${cfgoutputs_out} include/jemalloc/internal/jemalloc_internal.h"
|
||||
cfgoutputs_out="${cfgoutputs_out} test/jemalloc_test.h"
|
||||
|
||||
cfgoutputs_tup="Makefile doc/jemalloc${install_suffix}.3:doc/jemalloc.3.in"
|
||||
cfgoutputs_tup="Makefile"
|
||||
cfgoutputs_tup="${cfgoutputs_tup} doc/html.xsl:doc/html.xsl.in"
|
||||
cfgoutputs_tup="${cfgoutputs_tup} doc/manpages.xsl:doc/manpages.xsl.in"
|
||||
cfgoutputs_tup="${cfgoutputs_tup} doc/jemalloc${install_suffix}.xml:doc/jemalloc.xml.in"
|
||||
cfgoutputs_tup="${cfgoutputs_tup} include/jemalloc/jemalloc${install_suffix}.h:include/jemalloc/jemalloc.h.in"
|
||||
cfgoutputs_tup="${cfgoutputs_tup} include/jemalloc/internal/jemalloc_internal.h"
|
||||
cfgoutputs_tup="${cfgoutputs_tup} test/jemalloc_test.h:test/jemalloc_test.h.in"
|
||||
@@ -329,15 +361,6 @@ if test "x$enable_debug" = "x1" ; then
|
||||
AC_DEFINE([JEMALLOC_IVSALLOC], [ ])
|
||||
fi
|
||||
AC_SUBST([enable_debug])
|
||||
if test "x$enable_debug" = "x0" ; then
|
||||
roff_debug=".\\\" "
|
||||
roff_no_debug=""
|
||||
else
|
||||
roff_debug=""
|
||||
roff_no_debug=".\\\" "
|
||||
fi
|
||||
AC_SUBST([roff_debug])
|
||||
AC_SUBST([roff_no_debug])
|
||||
|
||||
dnl Only optimize if not debugging.
|
||||
if test "x$enable_debug" = "x0" -a "x$no_CFLAGS" = "xyes" ; then
|
||||
@@ -369,12 +392,6 @@ if test "x$enable_stats" = "x1" ; then
|
||||
AC_DEFINE([JEMALLOC_STATS], [ ])
|
||||
fi
|
||||
AC_SUBST([enable_stats])
|
||||
if test "x$enable_stats" = "x0" ; then
|
||||
roff_stats=".\\\" "
|
||||
else
|
||||
roff_stats=""
|
||||
fi
|
||||
AC_SUBST([roff_stats])
|
||||
|
||||
dnl Do not enable profiling by default.
|
||||
AC_ARG_ENABLE([prof],
|
||||
@@ -438,15 +455,6 @@ if test "x$enable_prof" = "x1" ; then
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([enable_prof])
|
||||
if test "x$enable_prof" = "x0" ; then
|
||||
roff_prof=".\\\" "
|
||||
roff_no_prof=""
|
||||
else
|
||||
roff_prof=""
|
||||
roff_no_prof=".\\\" "
|
||||
fi
|
||||
AC_SUBST([roff_prof])
|
||||
AC_SUBST([roff_no_prof])
|
||||
|
||||
dnl If libunwind isn't enabled, try to use libgcc rather than gcc intrinsics
|
||||
dnl for backtracing.
|
||||
@@ -478,15 +486,6 @@ if test "x$enable_tiny" = "x1" ; then
|
||||
AC_DEFINE([JEMALLOC_TINY], [ ])
|
||||
fi
|
||||
AC_SUBST([enable_tiny])
|
||||
if test "x$enable_tiny" = "x0" ; then
|
||||
roff_tiny=".\\\" "
|
||||
roff_no_tiny=""
|
||||
else
|
||||
roff_tiny=""
|
||||
roff_no_tiny=".\\\" "
|
||||
fi
|
||||
AC_SUBST([roff_tiny])
|
||||
AC_SUBST([roff_no_tiny])
|
||||
|
||||
dnl Enable thread-specific caching by default.
|
||||
AC_ARG_ENABLE([tcache],
|
||||
@@ -503,15 +502,6 @@ if test "x$enable_tcache" = "x1" ; then
|
||||
AC_DEFINE([JEMALLOC_TCACHE], [ ])
|
||||
fi
|
||||
AC_SUBST([enable_tcache])
|
||||
if test "x$enable_tcache" = "x0" ; then
|
||||
roff_tcache=".\\\" "
|
||||
roff_no_tcache=""
|
||||
else
|
||||
roff_tcache=""
|
||||
roff_no_tcache=".\\\" "
|
||||
fi
|
||||
AC_SUBST([roff_tcache])
|
||||
AC_SUBST([roff_no_tcache])
|
||||
|
||||
dnl Do not enable mmap()ped swap files by default.
|
||||
AC_ARG_ENABLE([swap],
|
||||
@@ -528,12 +518,6 @@ if test "x$enable_swap" = "x1" ; then
|
||||
AC_DEFINE([JEMALLOC_SWAP], [ ])
|
||||
fi
|
||||
AC_SUBST([enable_swap])
|
||||
if test "x$enable_swap" = "x0" ; then
|
||||
roff_swap=".\\\" "
|
||||
else
|
||||
roff_swap=""
|
||||
fi
|
||||
AC_SUBST([roff_swap])
|
||||
|
||||
dnl Do not enable allocation from DSS by default.
|
||||
AC_ARG_ENABLE([dss],
|
||||
@@ -550,12 +534,6 @@ if test "x$enable_dss" = "x1" ; then
|
||||
AC_DEFINE([JEMALLOC_DSS], [ ])
|
||||
fi
|
||||
AC_SUBST([enable_dss])
|
||||
if test "x$enable_dss" = "x0" ; then
|
||||
roff_dss=".\\\" "
|
||||
else
|
||||
roff_dss=""
|
||||
fi
|
||||
AC_SUBST([roff_dss])
|
||||
|
||||
dnl Do not support the junk/zero filling option by default.
|
||||
AC_ARG_ENABLE([fill],
|
||||
@@ -572,12 +550,6 @@ if test "x$enable_fill" = "x1" ; then
|
||||
AC_DEFINE([JEMALLOC_FILL], [ ])
|
||||
fi
|
||||
AC_SUBST([enable_fill])
|
||||
if test "x$enable_fill" = "x0" ; then
|
||||
roff_fill=".\\\" "
|
||||
else
|
||||
roff_fill=""
|
||||
fi
|
||||
AC_SUBST([roff_fill])
|
||||
|
||||
dnl Do not support the xmalloc option by default.
|
||||
AC_ARG_ENABLE([xmalloc],
|
||||
@@ -594,12 +566,6 @@ if test "x$enable_xmalloc" = "x1" ; then
|
||||
AC_DEFINE([JEMALLOC_XMALLOC], [ ])
|
||||
fi
|
||||
AC_SUBST([enable_xmalloc])
|
||||
if test "x$enable_xmalloc" = "x0" ; then
|
||||
roff_xmalloc=".\\\" "
|
||||
else
|
||||
roff_xmalloc=""
|
||||
fi
|
||||
AC_SUBST([roff_xmalloc])
|
||||
|
||||
dnl Do not support the SYSV option by default.
|
||||
AC_ARG_ENABLE([sysv],
|
||||
@@ -616,12 +582,6 @@ if test "x$enable_sysv" = "x1" ; then
|
||||
AC_DEFINE([JEMALLOC_SYSV], [ ])
|
||||
fi
|
||||
AC_SUBST([enable_sysv])
|
||||
if test "x$enable_sysv" = "x0" ; then
|
||||
roff_sysv=".\\\" "
|
||||
else
|
||||
roff_sysv=""
|
||||
fi
|
||||
AC_SUBST([roff_sysv])
|
||||
|
||||
dnl Do not determine page shift at run time by default.
|
||||
AC_ARG_ENABLE([dynamic_page_shift],
|
||||
@@ -828,6 +788,9 @@ AC_MSG_RESULT([LDFLAGS : ${LDFLAGS}])
|
||||
AC_MSG_RESULT([LIBS : ${LIBS}])
|
||||
AC_MSG_RESULT([RPATH_EXTRA : ${RPATH_EXTRA}])
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([XSLTPROC : ${XSLTPROC}])
|
||||
AC_MSG_RESULT([XSLROOT : ${XSLROOT}])
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([PREFIX : ${PREFIX}])
|
||||
AC_MSG_RESULT([BINDIR : ${BINDIR}])
|
||||
AC_MSG_RESULT([INCLUDEDIR : ${INCLUDEDIR}])
|
||||
|
||||
4
jemalloc/doc/html.xsl.in
Normal file
4
jemalloc/doc/html.xsl.in
Normal file
@@ -0,0 +1,4 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:import href="@XSLROOT@/html/docbook.xsl"/>
|
||||
<xsl:import href="@abs_srcroot@doc/stylesheet.xsl"/>
|
||||
</xsl:stylesheet>
|
||||
File diff suppressed because it is too large
Load Diff
2251
jemalloc/doc/jemalloc.xml.in
Normal file
2251
jemalloc/doc/jemalloc.xml.in
Normal file
File diff suppressed because it is too large
Load Diff
4
jemalloc/doc/manpages.xsl.in
Normal file
4
jemalloc/doc/manpages.xsl.in
Normal file
@@ -0,0 +1,4 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:import href="@XSLROOT@/manpages/docbook.xsl"/>
|
||||
<xsl:import href="@abs_srcroot@doc/stylesheet.xsl"/>
|
||||
</xsl:stylesheet>
|
||||
7
jemalloc/doc/stylesheet.xsl
Normal file
7
jemalloc/doc/stylesheet.xsl
Normal file
@@ -0,0 +1,7 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:param name="funcsynopsis.style">ansi</xsl:param>
|
||||
<xsl:param name="function.parens" select="1"/>
|
||||
<xsl:template match="mallctl">
|
||||
"<xsl:call-template name="inline.monoseq"/>"
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@@ -45,9 +45,10 @@
|
||||
* point is implicitly RUN_BFP bits to the left.
|
||||
*
|
||||
* Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be
|
||||
* honored for some/all object sizes, since there is one bit of header overhead
|
||||
* per object (plus a constant). This constraint is relaxed (ignored) for runs
|
||||
* that are so small that the per-region overhead is greater than:
|
||||
* honored for some/all object sizes, since when heap profiling is enabled
|
||||
* there is one pointer of header overhead per object (plus a constant). This
|
||||
* constraint is relaxed (ignored) for runs that are so small that the
|
||||
* per-region overhead is greater than:
|
||||
*
|
||||
* (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP))
|
||||
*/
|
||||
@@ -105,7 +106,7 @@ struct arena_chunk_map_s {
|
||||
* Run address (or size) and various flags are stored together. The bit
|
||||
* layout looks like (assuming 32-bit system):
|
||||
*
|
||||
* ???????? ???????? ????---- ----dzla
|
||||
* ???????? ???????? ????---- ----dula
|
||||
*
|
||||
* ? : Unallocated: Run address for first/last pages, unset for internal
|
||||
* pages.
|
||||
@@ -113,7 +114,7 @@ struct arena_chunk_map_s {
|
||||
* Large: Run size for first page, unset for trailing pages.
|
||||
* - : Unused.
|
||||
* d : dirty?
|
||||
* z : zeroed?
|
||||
* u : unzeroed?
|
||||
* l : large?
|
||||
* a : allocated?
|
||||
*
|
||||
@@ -129,30 +130,30 @@ struct arena_chunk_map_s {
|
||||
* [dula] : bit unset
|
||||
*
|
||||
* Unallocated (clean):
|
||||
* ssssssss ssssssss ssss---- ----du--
|
||||
* ssssssss ssssssss ssss---- ----du-a
|
||||
* xxxxxxxx xxxxxxxx xxxx---- -----Uxx
|
||||
* ssssssss ssssssss ssss---- ----dU--
|
||||
* ssssssss ssssssss ssss---- ----dU-a
|
||||
*
|
||||
* Unallocated (dirty):
|
||||
* ssssssss ssssssss ssss---- ----D---
|
||||
* ssssssss ssssssss ssss---- ----D--a
|
||||
* xxxxxxxx xxxxxxxx xxxx---- ----xxxx
|
||||
* ssssssss ssssssss ssss---- ----D---
|
||||
* ssssssss ssssssss ssss---- ----D--a
|
||||
*
|
||||
* Small:
|
||||
* pppppppp pppppppp pppp---- ----d--a
|
||||
* pppppppp pppppppp pppp---- -------a
|
||||
* pppppppp pppppppp pppp---- ----d--a
|
||||
* pppppppp pppppppp pppp---- ----d--A
|
||||
* pppppppp pppppppp pppp---- -------A
|
||||
* pppppppp pppppppp pppp---- ----d--A
|
||||
*
|
||||
* Large:
|
||||
* ssssssss ssssssss ssss---- ----D-la
|
||||
* ssssssss ssssssss ssss---- ----D-LA
|
||||
* xxxxxxxx xxxxxxxx xxxx---- ----xxxx
|
||||
* -------- -------- -------- ----D-la
|
||||
* -------- -------- -------- ----D-LA
|
||||
*
|
||||
* Large (sampled, size <= PAGE_SIZE):
|
||||
* ssssssss ssssssss sssscccc ccccD-la
|
||||
* ssssssss ssssssss sssscccc ccccD-LA
|
||||
*
|
||||
* Large (not sampled, size == PAGE_SIZE):
|
||||
* ssssssss ssssssss ssss---- ----D-la
|
||||
* ssssssss ssssssss ssss---- ----D-LA
|
||||
*/
|
||||
size_t bits;
|
||||
#ifdef JEMALLOC_PROF
|
||||
@@ -347,45 +348,35 @@ struct arena_s {
|
||||
|
||||
/*
|
||||
* bins is used to store trees of free regions of the following sizes,
|
||||
* assuming a 16-byte quantum, 4 KiB page size, and default
|
||||
* JEMALLOC_OPTIONS.
|
||||
* assuming a 64-bit system with 16-byte quantum, 4 KiB page size, and
|
||||
* default MALLOC_CONF.
|
||||
*
|
||||
* bins[i] | size |
|
||||
* --------+--------+
|
||||
* 0 | 2 |
|
||||
* 1 | 4 |
|
||||
* 2 | 8 |
|
||||
* 0 | 8 |
|
||||
* --------+--------+
|
||||
* 3 | 16 |
|
||||
* 4 | 32 |
|
||||
* 5 | 48 |
|
||||
* 1 | 16 |
|
||||
* 2 | 32 |
|
||||
* 3 | 48 |
|
||||
* : :
|
||||
* 8 | 96 |
|
||||
* 9 | 112 |
|
||||
* 10 | 128 |
|
||||
* 6 | 96 |
|
||||
* 7 | 112 |
|
||||
* 8 | 128 |
|
||||
* --------+--------+
|
||||
* 11 | 192 |
|
||||
* 12 | 256 |
|
||||
* 13 | 320 |
|
||||
* 14 | 384 |
|
||||
* 15 | 448 |
|
||||
* 16 | 512 |
|
||||
* 9 | 192 |
|
||||
* 10 | 256 |
|
||||
* 11 | 320 |
|
||||
* 12 | 384 |
|
||||
* 13 | 448 |
|
||||
* 14 | 512 |
|
||||
* --------+--------+
|
||||
* 17 | 768 |
|
||||
* 18 | 1024 |
|
||||
* 19 | 1280 |
|
||||
* 15 | 768 |
|
||||
* 16 | 1024 |
|
||||
* 17 | 1280 |
|
||||
* : :
|
||||
* 27 | 3328 |
|
||||
* 28 | 3584 |
|
||||
* 29 | 3840 |
|
||||
* --------+--------+
|
||||
* 30 | 4 KiB |
|
||||
* 31 | 6 KiB |
|
||||
* 33 | 8 KiB |
|
||||
* : :
|
||||
* 43 | 28 KiB |
|
||||
* 44 | 30 KiB |
|
||||
* 45 | 32 KiB |
|
||||
* 25 | 3328 |
|
||||
* 26 | 3584 |
|
||||
* 27 | 3840 |
|
||||
* --------+--------+
|
||||
*/
|
||||
arena_bin_t bins[1]; /* Dynamically sized. */
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
extern malloc_mutex_t dss_mtx;
|
||||
|
||||
void *chunk_alloc_dss(size_t size, bool *zero);
|
||||
bool chunk_in_dss(void *chunk);
|
||||
bool chunk_dealloc_dss(void *chunk, size_t size);
|
||||
bool chunk_dss_boot(void);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ extern size_t swap_avail;
|
||||
#endif
|
||||
|
||||
void *chunk_alloc_swap(size_t size, bool *zero);
|
||||
bool chunk_in_swap(void *chunk);
|
||||
bool chunk_dealloc_swap(void *chunk, size_t size);
|
||||
bool chunk_swap_enable(const int *fds, unsigned nfds, bool prezeroed);
|
||||
bool chunk_swap_boot(void);
|
||||
|
||||
@@ -31,7 +31,7 @@ struct ckhc_s {
|
||||
|
||||
struct ckh_s {
|
||||
#ifdef JEMALLOC_DEBUG
|
||||
#define CKH_MAGIG 0x3af2489d
|
||||
#define CKH_MAGIC 0x3af2489d
|
||||
uint32_t magic;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ hash(const void *key, size_t len, uint64_t seed)
|
||||
h *= m;
|
||||
h ^= h >> r;
|
||||
|
||||
return h;
|
||||
return (h);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ void *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);
|
||||
void huge_dalloc(void *ptr);
|
||||
void huge_dalloc(void *ptr, bool unmap);
|
||||
size_t huge_salloc(const void *ptr);
|
||||
#ifdef JEMALLOC_PROF
|
||||
prof_ctx_t *huge_prof_ctx_get(const void *ptr);
|
||||
|
||||
@@ -148,11 +148,6 @@ extern void (*JEMALLOC_P(malloc_message))(void *wcbopaque, const char *s);
|
||||
|
||||
#define SIZEOF_PTR (1U << LG_SIZEOF_PTR)
|
||||
|
||||
/* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */
|
||||
#if (!defined(PIC) && !defined(NO_TLS))
|
||||
# define NO_TLS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Maximum size of L1 cache line. This is used to avoid cache line aliasing.
|
||||
* In addition, this controls the spacing of cacheline-spaced size classes.
|
||||
@@ -240,6 +235,13 @@ extern void (*JEMALLOC_P(malloc_message))(void *wcbopaque, const char *s);
|
||||
#endif
|
||||
#include "jemalloc/internal/prof.h"
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
typedef struct {
|
||||
uint64_t allocated;
|
||||
uint64_t deallocated;
|
||||
} thread_allocated_t;
|
||||
#endif
|
||||
|
||||
#undef JEMALLOC_H_STRUCTS
|
||||
/******************************************************************************/
|
||||
#define JEMALLOC_H_EXTERNS
|
||||
@@ -295,45 +297,28 @@ extern arena_t **arenas;
|
||||
extern unsigned narenas;
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
typedef struct {
|
||||
uint64_t allocated;
|
||||
uint64_t deallocated;
|
||||
} thread_allocated_t;
|
||||
# ifndef NO_TLS
|
||||
extern __thread thread_allocated_t thread_allocated_tls;
|
||||
# define ALLOCATED_GET() thread_allocated_tls.allocated
|
||||
# define DEALLOCATED_GET() thread_allocated_tls.deallocated
|
||||
# define ALLOCATED_GET() (thread_allocated_tls.allocated)
|
||||
# define ALLOCATEDP_GET() (&thread_allocated_tls.allocated)
|
||||
# define DEALLOCATED_GET() (thread_allocated_tls.deallocated)
|
||||
# define DEALLOCATEDP_GET() (&thread_allocated_tls.deallocated)
|
||||
# define ALLOCATED_ADD(a, d) do { \
|
||||
thread_allocated_tls.allocated += a; \
|
||||
thread_allocated_tls.deallocated += d; \
|
||||
} while (0)
|
||||
# else
|
||||
extern pthread_key_t thread_allocated_tsd;
|
||||
# define ALLOCATED_GET() \
|
||||
(uint64_t)((pthread_getspecific(thread_allocated_tsd) != NULL) \
|
||||
? ((thread_allocated_t *) \
|
||||
pthread_getspecific(thread_allocated_tsd))->allocated : 0)
|
||||
# define DEALLOCATED_GET() \
|
||||
(uint64_t)((pthread_getspecific(thread_allocated_tsd) != NULL) \
|
||||
? ((thread_allocated_t \
|
||||
*)pthread_getspecific(thread_allocated_tsd))->deallocated : \
|
||||
0)
|
||||
thread_allocated_t *thread_allocated_get_hard(void);
|
||||
|
||||
# define ALLOCATED_GET() (thread_allocated_get()->allocated)
|
||||
# define ALLOCATEDP_GET() (&thread_allocated_get()->allocated)
|
||||
# define DEALLOCATED_GET() (thread_allocated_get()->deallocated)
|
||||
# define DEALLOCATEDP_GET() (&thread_allocated_get()->deallocated)
|
||||
# define ALLOCATED_ADD(a, d) do { \
|
||||
thread_allocated_t *thread_allocated = (thread_allocated_t *) \
|
||||
pthread_getspecific(thread_allocated_tsd); \
|
||||
if (thread_allocated != NULL) { \
|
||||
thread_allocated->allocated += (a); \
|
||||
thread_allocated->deallocated += (d); \
|
||||
} else { \
|
||||
thread_allocated = (thread_allocated_t *) \
|
||||
imalloc(sizeof(thread_allocated_t)); \
|
||||
if (thread_allocated != NULL) { \
|
||||
pthread_setspecific(thread_allocated_tsd, \
|
||||
thread_allocated); \
|
||||
thread_allocated->allocated = (a); \
|
||||
thread_allocated->deallocated = (d); \
|
||||
} \
|
||||
} \
|
||||
thread_allocated_t *thread_allocated = thread_allocated_get(); \
|
||||
thread_allocated->allocated += (a); \
|
||||
thread_allocated->deallocated += (d); \
|
||||
} while (0)
|
||||
# endif
|
||||
#endif
|
||||
@@ -384,6 +369,9 @@ size_t s2u(size_t size);
|
||||
size_t sa2u(size_t size, size_t alignment, size_t *run_size_p);
|
||||
void malloc_write(const char *s);
|
||||
arena_t *choose_arena(void);
|
||||
# ifdef NO_TLS
|
||||
thread_allocated_t *thread_allocated_get(void);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
|
||||
@@ -414,10 +402,10 @@ s2u(size_t size)
|
||||
{
|
||||
|
||||
if (size <= small_maxclass)
|
||||
return arenas[0]->bins[small_size2bin[size]].reg_size;
|
||||
return (arenas[0]->bins[small_size2bin[size]].reg_size);
|
||||
if (size <= arena_maxclass)
|
||||
return PAGE_CEILING(size);
|
||||
return CHUNK_CEILING(size);
|
||||
return (PAGE_CEILING(size));
|
||||
return (CHUNK_CEILING(size));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -544,6 +532,19 @@ choose_arena(void)
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef NO_TLS
|
||||
JEMALLOC_INLINE thread_allocated_t *
|
||||
thread_allocated_get(void)
|
||||
{
|
||||
thread_allocated_t *thread_allocated = (thread_allocated_t *)
|
||||
pthread_getspecific(thread_allocated_tsd);
|
||||
|
||||
if (thread_allocated == NULL)
|
||||
return (thread_allocated_get_hard());
|
||||
return (thread_allocated);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "jemalloc/internal/rtree.h"
|
||||
@@ -666,7 +667,7 @@ idalloc(void *ptr)
|
||||
if (chunk != ptr)
|
||||
arena_dalloc(chunk->arena, chunk, ptr);
|
||||
else
|
||||
huge_dalloc(ptr);
|
||||
huge_dalloc(ptr, true);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void *
|
||||
|
||||
@@ -37,7 +37,6 @@ struct tcache_bin_s {
|
||||
tcache_bin_stats_t tstats;
|
||||
# endif
|
||||
unsigned low_water; /* Min # cached since last GC. */
|
||||
unsigned high_water; /* Max # cached since last GC. */
|
||||
unsigned ncached; /* # of cached objects. */
|
||||
unsigned ncached_max; /* Upper limit on ncached. */
|
||||
void *avail; /* Chain of available objects. */
|
||||
@@ -194,7 +193,6 @@ tcache_event(tcache_t *tcache)
|
||||
}
|
||||
}
|
||||
tbin->low_water = tbin->ncached;
|
||||
tbin->high_water = tbin->ncached;
|
||||
|
||||
tcache->next_gc_bin++;
|
||||
if (tcache->next_gc_bin == nhbins)
|
||||
@@ -348,8 +346,6 @@ tcache_dalloc_small(tcache_t *tcache, void *ptr)
|
||||
*(void **)ptr = tbin->avail;
|
||||
tbin->avail = ptr;
|
||||
tbin->ncached++;
|
||||
if (tbin->ncached > tbin->high_water)
|
||||
tbin->high_water = tbin->ncached;
|
||||
|
||||
tcache_event(tcache);
|
||||
}
|
||||
@@ -388,8 +384,6 @@ tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size)
|
||||
*(void **)ptr = tbin->avail;
|
||||
tbin->avail = ptr;
|
||||
tbin->ncached++;
|
||||
if (tbin->ncached > tbin->high_water)
|
||||
tbin->high_water = tbin->ncached;
|
||||
|
||||
tcache_event(tcache);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ extern "C" {
|
||||
# define JEMALLOC_P(s) s
|
||||
#endif
|
||||
|
||||
#define ALLOCM_LG_ALIGN ((int)0x3f)
|
||||
#define ALLOCM_LG_ALIGN(la) (la)
|
||||
#if LG_SIZEOF_PTR == 2
|
||||
#define ALLOCM_ALIGN(a) (ffs(a)-1)
|
||||
#else
|
||||
|
||||
@@ -115,6 +115,9 @@
|
||||
#undef JEMALLOC_ZONE
|
||||
#undef JEMALLOC_ZONE_VERSION
|
||||
|
||||
/* If defined, use mremap(...MREMAP_FIXED...) for huge realloc(). */
|
||||
#undef JEMALLOC_MREMAP_FIXED
|
||||
|
||||
/*
|
||||
* Methods for purging unused pages differ between operating systems.
|
||||
*
|
||||
|
||||
@@ -304,8 +304,10 @@ arena_run_reg_dalloc(arena_run_t *run, void *ptr)
|
||||
static inline void
|
||||
arena_chunk_validate_zeroed(arena_chunk_t *chunk, size_t run_ind)
|
||||
{
|
||||
size_t i;
|
||||
size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << PAGE_SHIFT));
|
||||
for (size_t i = 0; i < PAGE_SIZE / sizeof(size_t); i++)
|
||||
|
||||
for (i = 0; i < PAGE_SIZE / sizeof(size_t); i++)
|
||||
assert(p[i] == 0);
|
||||
}
|
||||
#endif
|
||||
@@ -1356,8 +1358,6 @@ arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind
|
||||
#endif
|
||||
malloc_mutex_unlock(&bin->lock);
|
||||
tbin->ncached = i;
|
||||
if (tbin->ncached > tbin->high_water)
|
||||
tbin->high_water = tbin->ncached;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1367,7 +1367,6 @@ arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind
|
||||
* *) bin->run_size >= min_run_size
|
||||
* *) bin->run_size <= arena_maxclass
|
||||
* *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).
|
||||
* *) run header size < PAGE_SIZE
|
||||
*
|
||||
* bin->nregs and bin->reg0_offset are also calculated here, since these
|
||||
* settings are all interdependent.
|
||||
@@ -1453,8 +1452,7 @@ arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size)
|
||||
} while (try_run_size <= arena_maxclass
|
||||
&& try_run_size <= arena_maxclass
|
||||
&& RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX
|
||||
&& (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size
|
||||
&& try_hdr_size < PAGE_SIZE);
|
||||
&& (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size);
|
||||
|
||||
assert(good_hdr_size <= good_reg0_offset);
|
||||
|
||||
|
||||
@@ -146,11 +146,6 @@ chunk_boot(void)
|
||||
chunksize_mask = chunksize - 1;
|
||||
chunk_npages = (chunksize >> PAGE_SHIFT);
|
||||
|
||||
#ifdef JEMALLOC_IVSALLOC
|
||||
chunks_rtree = rtree_new((ZU(1) << (LG_SIZEOF_PTR+3)) - opt_lg_chunk);
|
||||
if (chunks_rtree == NULL)
|
||||
return (true);
|
||||
#endif
|
||||
#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
|
||||
if (malloc_mutex_init(&chunks_mtx))
|
||||
return (true);
|
||||
@@ -166,6 +161,11 @@ chunk_boot(void)
|
||||
if (chunk_dss_boot())
|
||||
return (true);
|
||||
#endif
|
||||
#ifdef JEMALLOC_IVSALLOC
|
||||
chunks_rtree = rtree_new((ZU(1) << (LG_SIZEOF_PTR+3)) - opt_lg_chunk);
|
||||
if (chunks_rtree == NULL)
|
||||
return (true);
|
||||
#endif
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
@@ -199,6 +199,22 @@ chunk_dealloc_dss_record(void *chunk, size_t size)
|
||||
return (node);
|
||||
}
|
||||
|
||||
bool
|
||||
chunk_in_dss(void *chunk)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
malloc_mutex_lock(&dss_mtx);
|
||||
if ((uintptr_t)chunk >= (uintptr_t)dss_base
|
||||
&& (uintptr_t)chunk < (uintptr_t)dss_max)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
malloc_mutex_unlock(&dss_mtx);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
bool
|
||||
chunk_dealloc_dss(void *chunk, size_t size)
|
||||
{
|
||||
|
||||
@@ -206,13 +206,15 @@ chunk_alloc_mmap_internal(size_t size, bool noreserve)
|
||||
void *
|
||||
chunk_alloc_mmap(size_t size)
|
||||
{
|
||||
return chunk_alloc_mmap_internal(size, false);
|
||||
|
||||
return (chunk_alloc_mmap_internal(size, false));
|
||||
}
|
||||
|
||||
void *
|
||||
chunk_alloc_mmap_noreserve(size_t size)
|
||||
{
|
||||
return chunk_alloc_mmap_internal(size, true);
|
||||
|
||||
return (chunk_alloc_mmap_internal(size, true));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -184,6 +184,24 @@ chunk_dealloc_swap_record(void *chunk, size_t size)
|
||||
return (node);
|
||||
}
|
||||
|
||||
bool
|
||||
chunk_in_swap(void *chunk)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
assert(swap_enabled);
|
||||
|
||||
malloc_mutex_lock(&swap_mtx);
|
||||
if ((uintptr_t)chunk >= (uintptr_t)swap_base
|
||||
&& (uintptr_t)chunk < (uintptr_t)swap_max)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
malloc_mutex_unlock(&swap_mtx);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
bool
|
||||
chunk_dealloc_swap(void *chunk, size_t size)
|
||||
{
|
||||
@@ -219,15 +237,15 @@ chunk_dealloc_swap(void *chunk, size_t size)
|
||||
} else
|
||||
madvise(chunk, size, MADV_DONTNEED);
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
swap_avail += size;
|
||||
#endif
|
||||
ret = false;
|
||||
goto RETURN;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
RETURN:
|
||||
#ifdef JEMALLOC_STATS
|
||||
swap_avail += size;
|
||||
#endif
|
||||
malloc_mutex_unlock(&swap_mtx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ ckh_isearch(ckh_t *ckh, const void *key)
|
||||
size_t hash1, hash2, bucket, cell;
|
||||
|
||||
assert(ckh != NULL);
|
||||
assert(ckh->magic = CKH_MAGIG);
|
||||
assert(ckh->magic == CKH_MAGIC);
|
||||
|
||||
ckh->hash(key, ckh->lg_curbuckets, &hash1, &hash2);
|
||||
|
||||
@@ -383,7 +383,7 @@ ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp)
|
||||
}
|
||||
|
||||
#ifdef JEMALLOC_DEBUG
|
||||
ckh->magic = CKH_MAGIG;
|
||||
ckh->magic = CKH_MAGIC;
|
||||
#endif
|
||||
|
||||
ret = false;
|
||||
@@ -396,7 +396,7 @@ ckh_delete(ckh_t *ckh)
|
||||
{
|
||||
|
||||
assert(ckh != NULL);
|
||||
assert(ckh->magic = CKH_MAGIG);
|
||||
assert(ckh->magic == CKH_MAGIC);
|
||||
|
||||
#ifdef CKH_VERBOSE
|
||||
malloc_printf(
|
||||
@@ -421,7 +421,7 @@ ckh_count(ckh_t *ckh)
|
||||
{
|
||||
|
||||
assert(ckh != NULL);
|
||||
assert(ckh->magic = CKH_MAGIG);
|
||||
assert(ckh->magic == CKH_MAGIC);
|
||||
|
||||
return (ckh->count);
|
||||
}
|
||||
@@ -452,7 +452,7 @@ ckh_insert(ckh_t *ckh, const void *key, const void *data)
|
||||
bool ret;
|
||||
|
||||
assert(ckh != NULL);
|
||||
assert(ckh->magic = CKH_MAGIG);
|
||||
assert(ckh->magic == CKH_MAGIC);
|
||||
assert(ckh_search(ckh, key, NULL, NULL));
|
||||
|
||||
#ifdef CKH_COUNT
|
||||
@@ -477,7 +477,7 @@ ckh_remove(ckh_t *ckh, const void *searchkey, void **key, void **data)
|
||||
size_t cell;
|
||||
|
||||
assert(ckh != NULL);
|
||||
assert(ckh->magic = CKH_MAGIG);
|
||||
assert(ckh->magic == CKH_MAGIC);
|
||||
|
||||
cell = ckh_isearch(ckh, searchkey);
|
||||
if (cell != SIZE_T_MAX) {
|
||||
@@ -509,7 +509,7 @@ ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data)
|
||||
size_t cell;
|
||||
|
||||
assert(ckh != NULL);
|
||||
assert(ckh->magic = CKH_MAGIG);
|
||||
assert(ckh->magic == CKH_MAGIC);
|
||||
|
||||
cell = ckh_isearch(ckh, searchkey);
|
||||
if (cell != SIZE_T_MAX) {
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
/******************************************************************************/
|
||||
/* Data. */
|
||||
|
||||
/*
|
||||
* ctl_mtx protects the following:
|
||||
* - ctl_stats.*
|
||||
* - opt_prof_active
|
||||
* - swap_enabled
|
||||
* - swap_prezeroed
|
||||
*/
|
||||
static malloc_mutex_t ctl_mtx;
|
||||
static bool ctl_initialized;
|
||||
static uint64_t ctl_epoch;
|
||||
@@ -44,7 +51,9 @@ CTL_PROTO(tcache_flush)
|
||||
CTL_PROTO(thread_arena)
|
||||
#ifdef JEMALLOC_STATS
|
||||
CTL_PROTO(thread_allocated)
|
||||
CTL_PROTO(thread_allocatedp)
|
||||
CTL_PROTO(thread_deallocated)
|
||||
CTL_PROTO(thread_deallocatedp)
|
||||
#endif
|
||||
CTL_PROTO(config_debug)
|
||||
CTL_PROTO(config_dss)
|
||||
@@ -223,7 +232,9 @@ static const ctl_node_t thread_node[] = {
|
||||
#ifdef JEMALLOC_STATS
|
||||
,
|
||||
{NAME("allocated"), CTL(thread_allocated)},
|
||||
{NAME("deallocated"), CTL(thread_deallocated)}
|
||||
{NAME("allocatedp"), CTL(thread_allocatedp)},
|
||||
{NAME("deallocated"), CTL(thread_deallocated)},
|
||||
{NAME("deallocatedp"), CTL(thread_deallocatedp)}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -680,7 +691,9 @@ ctl_refresh(void)
|
||||
static bool
|
||||
ctl_init(void)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
malloc_mutex_lock(&ctl_mtx);
|
||||
if (ctl_initialized == false) {
|
||||
#ifdef JEMALLOC_STATS
|
||||
unsigned i;
|
||||
@@ -692,8 +705,10 @@ ctl_init(void)
|
||||
*/
|
||||
ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc(
|
||||
(narenas + 1) * sizeof(ctl_arena_stats_t));
|
||||
if (ctl_stats.arenas == NULL)
|
||||
return (true);
|
||||
if (ctl_stats.arenas == NULL) {
|
||||
ret = true;
|
||||
goto RETURN;
|
||||
}
|
||||
memset(ctl_stats.arenas, 0, (narenas + 1) *
|
||||
sizeof(ctl_arena_stats_t));
|
||||
|
||||
@@ -704,8 +719,10 @@ ctl_init(void)
|
||||
*/
|
||||
#ifdef JEMALLOC_STATS
|
||||
for (i = 0; i <= narenas; i++) {
|
||||
if (ctl_arena_init(&ctl_stats.arenas[i]))
|
||||
return (true);
|
||||
if (ctl_arena_init(&ctl_stats.arenas[i])) {
|
||||
ret = true;
|
||||
goto RETURN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ctl_stats.arenas[narenas].initialized = true;
|
||||
@@ -715,7 +732,10 @@ ctl_init(void)
|
||||
ctl_initialized = true;
|
||||
}
|
||||
|
||||
return (false);
|
||||
ret = false;
|
||||
RETURN:
|
||||
malloc_mutex_unlock(&ctl_mtx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -825,8 +845,7 @@ ctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,
|
||||
ctl_node_t const *nodes[CTL_MAX_DEPTH];
|
||||
size_t mib[CTL_MAX_DEPTH];
|
||||
|
||||
malloc_mutex_lock(&ctl_mtx);
|
||||
if (ctl_init()) {
|
||||
if (ctl_initialized == false && ctl_init()) {
|
||||
ret = EAGAIN;
|
||||
goto RETURN;
|
||||
}
|
||||
@@ -841,10 +860,9 @@ ctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,
|
||||
ret = ENOENT;
|
||||
goto RETURN;
|
||||
}
|
||||
ret = nodes[depth-1]->ctl(mib, depth, oldp, oldlenp, newp, newlen);
|
||||
|
||||
ret = nodes[depth-1]->ctl(mib, depth, oldp, oldlenp, newp, newlen);
|
||||
RETURN:
|
||||
malloc_mutex_unlock(&ctl_mtx);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@@ -853,16 +871,13 @@ ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
malloc_mutex_lock(&ctl_mtx);
|
||||
if (ctl_init()) {
|
||||
if (ctl_initialized == false && ctl_init()) {
|
||||
ret = EAGAIN;
|
||||
goto RETURN;
|
||||
}
|
||||
|
||||
ret = ctl_lookup(name, NULL, mibp, miblenp);
|
||||
|
||||
RETURN:
|
||||
malloc_mutex_unlock(&ctl_mtx);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@@ -874,8 +889,7 @@ ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
const ctl_node_t *node;
|
||||
size_t i;
|
||||
|
||||
malloc_mutex_lock(&ctl_mtx);
|
||||
if (ctl_init()) {
|
||||
if (ctl_initialized == false && ctl_init()) {
|
||||
ret = EAGAIN;
|
||||
goto RETURN;
|
||||
}
|
||||
@@ -912,7 +926,6 @@ ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
ret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen);
|
||||
|
||||
RETURN:
|
||||
malloc_mutex_unlock(&ctl_mtx);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@@ -975,6 +988,29 @@ ctl_boot(void)
|
||||
|
||||
#define CTL_RO_GEN(n, v, t) \
|
||||
static int \
|
||||
n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
|
||||
void *newp, size_t newlen) \
|
||||
{ \
|
||||
int ret; \
|
||||
t oldval; \
|
||||
\
|
||||
malloc_mutex_lock(&ctl_mtx); \
|
||||
READONLY(); \
|
||||
oldval = v; \
|
||||
READ(oldval, t); \
|
||||
\
|
||||
ret = 0; \
|
||||
RETURN: \
|
||||
malloc_mutex_unlock(&ctl_mtx); \
|
||||
return (ret); \
|
||||
}
|
||||
|
||||
/*
|
||||
* ctl_mtx is not acquired, under the assumption that no pertinent data will
|
||||
* mutate during the call.
|
||||
*/
|
||||
#define CTL_RO_NL_GEN(n, v, t) \
|
||||
static int \
|
||||
n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
|
||||
void *newp, size_t newlen) \
|
||||
{ \
|
||||
@@ -1024,7 +1060,7 @@ RETURN: \
|
||||
return (ret); \
|
||||
}
|
||||
|
||||
CTL_RO_GEN(version, JEMALLOC_VERSION, const char *)
|
||||
CTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)
|
||||
|
||||
static int
|
||||
epoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
@@ -1033,6 +1069,7 @@ epoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
int ret;
|
||||
uint64_t newval;
|
||||
|
||||
malloc_mutex_lock(&ctl_mtx);
|
||||
newval = 0;
|
||||
WRITE(newval, uint64_t);
|
||||
if (newval != 0)
|
||||
@@ -1041,6 +1078,7 @@ epoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
|
||||
ret = 0;
|
||||
RETURN:
|
||||
malloc_mutex_unlock(&ctl_mtx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -1099,6 +1137,11 @@ thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
|
||||
/* Set new arena association. */
|
||||
ARENA_SET(arena);
|
||||
{
|
||||
tcache_t *tcache = TCACHE_GET();
|
||||
if (tcache != NULL)
|
||||
tcache->arena = arena;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
@@ -1107,8 +1150,10 @@ RETURN:
|
||||
}
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
CTL_RO_GEN(thread_allocated, ALLOCATED_GET(), uint64_t);
|
||||
CTL_RO_GEN(thread_deallocated, DEALLOCATED_GET(), uint64_t);
|
||||
CTL_RO_NL_GEN(thread_allocated, ALLOCATED_GET(), uint64_t);
|
||||
CTL_RO_NL_GEN(thread_allocatedp, ALLOCATEDP_GET(), uint64_t *);
|
||||
CTL_RO_NL_GEN(thread_deallocated, DEALLOCATED_GET(), uint64_t);
|
||||
CTL_RO_NL_GEN(thread_deallocatedp, DEALLOCATEDP_GET(), uint64_t *);
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -1205,48 +1250,48 @@ CTL_RO_FALSE_GEN(config_xmalloc)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
CTL_RO_GEN(opt_abort, opt_abort, bool)
|
||||
CTL_RO_GEN(opt_lg_qspace_max, opt_lg_qspace_max, size_t)
|
||||
CTL_RO_GEN(opt_lg_cspace_max, opt_lg_cspace_max, size_t)
|
||||
CTL_RO_GEN(opt_lg_chunk, opt_lg_chunk, size_t)
|
||||
CTL_RO_GEN(opt_narenas, opt_narenas, size_t)
|
||||
CTL_RO_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)
|
||||
CTL_RO_GEN(opt_stats_print, opt_stats_print, bool)
|
||||
CTL_RO_NL_GEN(opt_abort, opt_abort, bool)
|
||||
CTL_RO_NL_GEN(opt_lg_qspace_max, opt_lg_qspace_max, size_t)
|
||||
CTL_RO_NL_GEN(opt_lg_cspace_max, opt_lg_cspace_max, size_t)
|
||||
CTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)
|
||||
CTL_RO_NL_GEN(opt_narenas, opt_narenas, size_t)
|
||||
CTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)
|
||||
CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
|
||||
#ifdef JEMALLOC_FILL
|
||||
CTL_RO_GEN(opt_junk, opt_junk, bool)
|
||||
CTL_RO_GEN(opt_zero, opt_zero, bool)
|
||||
CTL_RO_NL_GEN(opt_junk, opt_junk, bool)
|
||||
CTL_RO_NL_GEN(opt_zero, opt_zero, bool)
|
||||
#endif
|
||||
#ifdef JEMALLOC_SYSV
|
||||
CTL_RO_GEN(opt_sysv, opt_sysv, bool)
|
||||
CTL_RO_NL_GEN(opt_sysv, opt_sysv, bool)
|
||||
#endif
|
||||
#ifdef JEMALLOC_XMALLOC
|
||||
CTL_RO_GEN(opt_xmalloc, opt_xmalloc, bool)
|
||||
CTL_RO_NL_GEN(opt_xmalloc, opt_xmalloc, bool)
|
||||
#endif
|
||||
#ifdef JEMALLOC_TCACHE
|
||||
CTL_RO_GEN(opt_tcache, opt_tcache, bool)
|
||||
CTL_RO_GEN(opt_lg_tcache_gc_sweep, opt_lg_tcache_gc_sweep, ssize_t)
|
||||
CTL_RO_NL_GEN(opt_tcache, opt_tcache, bool)
|
||||
CTL_RO_NL_GEN(opt_lg_tcache_gc_sweep, opt_lg_tcache_gc_sweep, ssize_t)
|
||||
#endif
|
||||
#ifdef JEMALLOC_PROF
|
||||
CTL_RO_GEN(opt_prof, opt_prof, bool)
|
||||
CTL_RO_GEN(opt_prof_prefix, opt_prof_prefix, const char *)
|
||||
CTL_RO_GEN(opt_prof_active, opt_prof_active, bool)
|
||||
CTL_RO_GEN(opt_lg_prof_bt_max, opt_lg_prof_bt_max, size_t)
|
||||
CTL_RO_GEN(opt_lg_prof_sample, opt_lg_prof_sample, size_t)
|
||||
CTL_RO_GEN(opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
|
||||
CTL_RO_GEN(opt_prof_gdump, opt_prof_gdump, bool)
|
||||
CTL_RO_GEN(opt_prof_leak, opt_prof_leak, bool)
|
||||
CTL_RO_GEN(opt_prof_accum, opt_prof_accum, bool)
|
||||
CTL_RO_GEN(opt_lg_prof_tcmax, opt_lg_prof_tcmax, ssize_t)
|
||||
CTL_RO_NL_GEN(opt_prof, opt_prof, bool)
|
||||
CTL_RO_NL_GEN(opt_prof_prefix, opt_prof_prefix, const char *)
|
||||
CTL_RO_GEN(opt_prof_active, opt_prof_active, bool) /* Mutable. */
|
||||
CTL_RO_NL_GEN(opt_lg_prof_bt_max, opt_lg_prof_bt_max, size_t)
|
||||
CTL_RO_NL_GEN(opt_lg_prof_sample, opt_lg_prof_sample, size_t)
|
||||
CTL_RO_NL_GEN(opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
|
||||
CTL_RO_NL_GEN(opt_prof_gdump, opt_prof_gdump, bool)
|
||||
CTL_RO_NL_GEN(opt_prof_leak, opt_prof_leak, bool)
|
||||
CTL_RO_NL_GEN(opt_prof_accum, opt_prof_accum, bool)
|
||||
CTL_RO_NL_GEN(opt_lg_prof_tcmax, opt_lg_prof_tcmax, ssize_t)
|
||||
#endif
|
||||
#ifdef JEMALLOC_SWAP
|
||||
CTL_RO_GEN(opt_overcommit, opt_overcommit, bool)
|
||||
CTL_RO_NL_GEN(opt_overcommit, opt_overcommit, bool)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
CTL_RO_GEN(arenas_bin_i_size, arenas[0]->bins[mib[2]].reg_size, size_t)
|
||||
CTL_RO_GEN(arenas_bin_i_nregs, arenas[0]->bins[mib[2]].nregs, uint32_t)
|
||||
CTL_RO_GEN(arenas_bin_i_run_size, arenas[0]->bins[mib[2]].run_size, size_t)
|
||||
CTL_RO_NL_GEN(arenas_bin_i_size, arenas[0]->bins[mib[2]].reg_size, size_t)
|
||||
CTL_RO_NL_GEN(arenas_bin_i_nregs, arenas[0]->bins[mib[2]].nregs, uint32_t)
|
||||
CTL_RO_NL_GEN(arenas_bin_i_run_size, arenas[0]->bins[mib[2]].run_size, size_t)
|
||||
const ctl_node_t *
|
||||
arenas_bin_i_index(const size_t *mib, size_t miblen, size_t i)
|
||||
{
|
||||
@@ -1256,7 +1301,7 @@ arenas_bin_i_index(const size_t *mib, size_t miblen, size_t i)
|
||||
return (super_arenas_bin_i_node);
|
||||
}
|
||||
|
||||
CTL_RO_GEN(arenas_lrun_i_size, ((mib[2]+1) << PAGE_SHIFT), size_t)
|
||||
CTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << PAGE_SHIFT), size_t)
|
||||
const ctl_node_t *
|
||||
arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i)
|
||||
{
|
||||
@@ -1266,7 +1311,7 @@ arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i)
|
||||
return (super_arenas_lrun_i_node);
|
||||
}
|
||||
|
||||
CTL_RO_GEN(arenas_narenas, narenas, unsigned)
|
||||
CTL_RO_NL_GEN(arenas_narenas, narenas, unsigned)
|
||||
|
||||
static int
|
||||
arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp,
|
||||
@@ -1275,6 +1320,7 @@ arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp,
|
||||
int ret;
|
||||
unsigned nread, i;
|
||||
|
||||
malloc_mutex_lock(&ctl_mtx);
|
||||
READONLY();
|
||||
if (*oldlenp != narenas * sizeof(bool)) {
|
||||
ret = EINVAL;
|
||||
@@ -1289,36 +1335,37 @@ arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp,
|
||||
((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;
|
||||
|
||||
RETURN:
|
||||
malloc_mutex_unlock(&ctl_mtx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
CTL_RO_GEN(arenas_quantum, QUANTUM, size_t)
|
||||
CTL_RO_GEN(arenas_cacheline, CACHELINE, size_t)
|
||||
CTL_RO_GEN(arenas_subpage, SUBPAGE, size_t)
|
||||
CTL_RO_GEN(arenas_pagesize, PAGE_SIZE, size_t)
|
||||
CTL_RO_GEN(arenas_chunksize, chunksize, size_t)
|
||||
CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)
|
||||
CTL_RO_NL_GEN(arenas_cacheline, CACHELINE, size_t)
|
||||
CTL_RO_NL_GEN(arenas_subpage, SUBPAGE, size_t)
|
||||
CTL_RO_NL_GEN(arenas_pagesize, PAGE_SIZE, size_t)
|
||||
CTL_RO_NL_GEN(arenas_chunksize, chunksize, size_t)
|
||||
#ifdef JEMALLOC_TINY
|
||||
CTL_RO_GEN(arenas_tspace_min, (1U << LG_TINY_MIN), size_t)
|
||||
CTL_RO_GEN(arenas_tspace_max, (qspace_min >> 1), size_t)
|
||||
CTL_RO_NL_GEN(arenas_tspace_min, (1U << LG_TINY_MIN), size_t)
|
||||
CTL_RO_NL_GEN(arenas_tspace_max, (qspace_min >> 1), size_t)
|
||||
#endif
|
||||
CTL_RO_GEN(arenas_qspace_min, qspace_min, size_t)
|
||||
CTL_RO_GEN(arenas_qspace_max, qspace_max, size_t)
|
||||
CTL_RO_GEN(arenas_cspace_min, cspace_min, size_t)
|
||||
CTL_RO_GEN(arenas_cspace_max, cspace_max, size_t)
|
||||
CTL_RO_GEN(arenas_sspace_min, sspace_min, size_t)
|
||||
CTL_RO_GEN(arenas_sspace_max, sspace_max, size_t)
|
||||
CTL_RO_NL_GEN(arenas_qspace_min, qspace_min, size_t)
|
||||
CTL_RO_NL_GEN(arenas_qspace_max, qspace_max, size_t)
|
||||
CTL_RO_NL_GEN(arenas_cspace_min, cspace_min, size_t)
|
||||
CTL_RO_NL_GEN(arenas_cspace_max, cspace_max, size_t)
|
||||
CTL_RO_NL_GEN(arenas_sspace_min, sspace_min, size_t)
|
||||
CTL_RO_NL_GEN(arenas_sspace_max, sspace_max, size_t)
|
||||
#ifdef JEMALLOC_TCACHE
|
||||
CTL_RO_GEN(arenas_tcache_max, tcache_maxclass, size_t)
|
||||
CTL_RO_NL_GEN(arenas_tcache_max, tcache_maxclass, size_t)
|
||||
#endif
|
||||
CTL_RO_GEN(arenas_ntbins, ntbins, unsigned)
|
||||
CTL_RO_GEN(arenas_nqbins, nqbins, unsigned)
|
||||
CTL_RO_GEN(arenas_ncbins, ncbins, unsigned)
|
||||
CTL_RO_GEN(arenas_nsbins, nsbins, unsigned)
|
||||
CTL_RO_GEN(arenas_nbins, nbins, unsigned)
|
||||
CTL_RO_NL_GEN(arenas_ntbins, ntbins, unsigned)
|
||||
CTL_RO_NL_GEN(arenas_nqbins, nqbins, unsigned)
|
||||
CTL_RO_NL_GEN(arenas_ncbins, ncbins, unsigned)
|
||||
CTL_RO_NL_GEN(arenas_nsbins, nsbins, unsigned)
|
||||
CTL_RO_NL_GEN(arenas_nbins, nbins, unsigned)
|
||||
#ifdef JEMALLOC_TCACHE
|
||||
CTL_RO_GEN(arenas_nhbins, nhbins, unsigned)
|
||||
CTL_RO_NL_GEN(arenas_nhbins, nhbins, unsigned)
|
||||
#endif
|
||||
CTL_RO_GEN(arenas_nlruns, nlclasses, size_t)
|
||||
CTL_RO_NL_GEN(arenas_nlruns, nlclasses, size_t)
|
||||
|
||||
static int
|
||||
arenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
@@ -1368,6 +1415,7 @@ prof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
int ret;
|
||||
bool oldval;
|
||||
|
||||
malloc_mutex_lock(&ctl_mtx); /* Protect opt_prof_active. */
|
||||
oldval = opt_prof_active;
|
||||
if (newp != NULL) {
|
||||
/*
|
||||
@@ -1382,6 +1430,7 @@ prof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
|
||||
ret = 0;
|
||||
RETURN:
|
||||
malloc_mutex_unlock(&ctl_mtx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -1405,7 +1454,7 @@ RETURN:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
CTL_RO_GEN(prof_interval, prof_interval, uint64_t)
|
||||
CTL_RO_NL_GEN(prof_interval, prof_interval, uint64_t)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -1503,10 +1552,18 @@ CTL_RO_GEN(stats_arenas_i_purged, ctl_stats.arenas[mib[2]].astats.purged,
|
||||
const ctl_node_t *
|
||||
stats_arenas_i_index(const size_t *mib, size_t miblen, size_t i)
|
||||
{
|
||||
const ctl_node_t * ret;
|
||||
|
||||
if (ctl_stats.arenas[i].initialized == false)
|
||||
return (NULL);
|
||||
return (super_stats_arenas_i_node);
|
||||
malloc_mutex_lock(&ctl_mtx);
|
||||
if (ctl_stats.arenas[i].initialized == false) {
|
||||
ret = NULL;
|
||||
goto RETURN;
|
||||
}
|
||||
|
||||
ret = super_stats_arenas_i_node;
|
||||
RETURN:
|
||||
malloc_mutex_unlock(&ctl_mtx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
@@ -1528,6 +1585,7 @@ swap_prezeroed_ctl(const size_t *mib, size_t miblen, void *oldp,
|
||||
{
|
||||
int ret;
|
||||
|
||||
malloc_mutex_lock(&ctl_mtx);
|
||||
if (swap_enabled) {
|
||||
READONLY();
|
||||
} else {
|
||||
@@ -1545,6 +1603,7 @@ swap_prezeroed_ctl(const size_t *mib, size_t miblen, void *oldp,
|
||||
|
||||
ret = 0;
|
||||
RETURN:
|
||||
malloc_mutex_unlock(&ctl_mtx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -1556,6 +1615,7 @@ swap_fds_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
{
|
||||
int ret;
|
||||
|
||||
malloc_mutex_lock(&ctl_mtx);
|
||||
if (swap_enabled) {
|
||||
READONLY();
|
||||
} else if (newp != NULL) {
|
||||
@@ -1586,6 +1646,7 @@ swap_fds_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
|
||||
ret = 0;
|
||||
RETURN:
|
||||
malloc_mutex_unlock(&ctl_mtx);
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -83,7 +83,7 @@ huge_palloc(size_t size, size_t alignment, bool zero)
|
||||
* alignment, in order to assure the alignment can be achieved, then
|
||||
* unmap leading and trailing chunks.
|
||||
*/
|
||||
assert(alignment >= chunksize);
|
||||
assert(alignment > chunksize);
|
||||
|
||||
chunk_size = CHUNK_CEILING(size);
|
||||
|
||||
@@ -192,7 +192,7 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
* different size class. In that case, fall back to allocating new
|
||||
* space and copying.
|
||||
*/
|
||||
if (alignment != 0)
|
||||
if (alignment > chunksize)
|
||||
ret = huge_palloc(size + extra, alignment, zero);
|
||||
else
|
||||
ret = huge_malloc(size + extra, zero);
|
||||
@@ -201,7 +201,7 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
if (extra == 0)
|
||||
return (NULL);
|
||||
/* Try again, this time without extra. */
|
||||
if (alignment != 0)
|
||||
if (alignment > chunksize)
|
||||
ret = huge_palloc(size, alignment, zero);
|
||||
else
|
||||
ret = huge_malloc(size, zero);
|
||||
@@ -215,13 +215,56 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
* expectation that the extra bytes will be reliably preserved.
|
||||
*/
|
||||
copysize = (size < oldsize) ? size : oldsize;
|
||||
memcpy(ret, ptr, copysize);
|
||||
idalloc(ptr);
|
||||
|
||||
/*
|
||||
* Use mremap(2) if this is a huge-->huge reallocation, and neither the
|
||||
* source nor the destination are in swap or dss.
|
||||
*/
|
||||
#ifdef JEMALLOC_MREMAP_FIXED
|
||||
if (oldsize >= chunksize
|
||||
# ifdef JEMALLOC_SWAP
|
||||
&& (swap_enabled == false || (chunk_in_swap(ptr) == false &&
|
||||
chunk_in_swap(ret) == false))
|
||||
# endif
|
||||
# ifdef JEMALLOC_DSS
|
||||
&& chunk_in_dss(ptr) == false && chunk_in_dss(ret) == false
|
||||
# endif
|
||||
) {
|
||||
size_t newsize = huge_salloc(ret);
|
||||
|
||||
if (mremap(ptr, oldsize, newsize, MREMAP_MAYMOVE|MREMAP_FIXED,
|
||||
ret) == MAP_FAILED) {
|
||||
/*
|
||||
* Assuming no chunk management bugs in the allocator,
|
||||
* the only documented way an error can occur here is
|
||||
* if the application changed the map type for a
|
||||
* portion of the old allocation. This is firmly in
|
||||
* undefined behavior territory, so write a diagnostic
|
||||
* message, and optionally abort.
|
||||
*/
|
||||
char buf[BUFERROR_BUF];
|
||||
|
||||
buferror(errno, buf, sizeof(buf));
|
||||
malloc_write("<jemalloc>: Error in mremap(): ");
|
||||
malloc_write(buf);
|
||||
malloc_write("\n");
|
||||
if (opt_abort)
|
||||
abort();
|
||||
memcpy(ret, ptr, copysize);
|
||||
idalloc(ptr);
|
||||
} else
|
||||
huge_dalloc(ptr, false);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
memcpy(ret, ptr, copysize);
|
||||
idalloc(ptr);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
huge_dalloc(void *ptr)
|
||||
huge_dalloc(void *ptr, bool unmap)
|
||||
{
|
||||
extent_node_t *node, key;
|
||||
|
||||
@@ -241,14 +284,16 @@ huge_dalloc(void *ptr)
|
||||
|
||||
malloc_mutex_unlock(&huge_mtx);
|
||||
|
||||
if (unmap) {
|
||||
/* Unmap chunk. */
|
||||
#ifdef JEMALLOC_FILL
|
||||
#if (defined(JEMALLOC_SWAP) || defined(JEMALLOC_DSS))
|
||||
if (opt_junk)
|
||||
memset(node->addr, 0x5a, node->size);
|
||||
if (opt_junk)
|
||||
memset(node->addr, 0x5a, node->size);
|
||||
#endif
|
||||
#endif
|
||||
chunk_dealloc(node->addr, node->size);
|
||||
chunk_dealloc(node->addr, node->size);
|
||||
}
|
||||
|
||||
base_node_dealloc(node);
|
||||
}
|
||||
|
||||
@@ -213,6 +213,28 @@ stats_print_atexit(void)
|
||||
JEMALLOC_P(malloc_stats_print)(NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
#if (defined(JEMALLOC_STATS) && defined(NO_TLS))
|
||||
thread_allocated_t *
|
||||
thread_allocated_get_hard(void)
|
||||
{
|
||||
thread_allocated_t *thread_allocated = (thread_allocated_t *)
|
||||
imalloc(sizeof(thread_allocated_t));
|
||||
if (thread_allocated == NULL) {
|
||||
static thread_allocated_t static_thread_allocated = {0, 0};
|
||||
malloc_write("<jemalloc>: Error allocating TSD;"
|
||||
" mallctl(\"thread.{de,}allocated[p]\", ...)"
|
||||
" will be inaccurate\n");
|
||||
if (opt_abort)
|
||||
abort();
|
||||
return (&static_thread_allocated);
|
||||
}
|
||||
pthread_setspecific(thread_allocated_tsd, thread_allocated);
|
||||
thread_allocated->allocated = 0;
|
||||
thread_allocated->deallocated = 0;
|
||||
return (thread_allocated);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* End miscellaneous support functions.
|
||||
*/
|
||||
@@ -421,8 +443,8 @@ malloc_conf_init(void)
|
||||
if ((opts = getenv(envname)) != NULL) {
|
||||
/*
|
||||
* Do nothing; opts is already initialized to
|
||||
* the value of the JEMALLOC_OPTIONS
|
||||
* environment variable.
|
||||
* the value of the MALLOC_CONF environment
|
||||
* variable.
|
||||
*/
|
||||
} else {
|
||||
/* No configuration specified. */
|
||||
|
||||
@@ -255,6 +255,7 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max)
|
||||
} else \
|
||||
return;
|
||||
|
||||
assert(nignore <= 3);
|
||||
assert(max <= (1U << opt_lg_prof_bt_max));
|
||||
|
||||
BT_FRAME(0)
|
||||
@@ -398,7 +399,7 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max)
|
||||
BT_FRAME(126)
|
||||
BT_FRAME(127)
|
||||
|
||||
/* Extras to compensate for NIGNORE. */
|
||||
/* Extras to compensate for nignore. */
|
||||
BT_FRAME(128)
|
||||
BT_FRAME(129)
|
||||
BT_FRAME(130)
|
||||
@@ -431,6 +432,7 @@ prof_lookup(prof_bt_t *bt)
|
||||
prof_ctx_t *p;
|
||||
void *v;
|
||||
} ctx;
|
||||
bool new_ctx;
|
||||
|
||||
/*
|
||||
* This thread's cache lacks bt. Look for it in the global
|
||||
@@ -467,12 +469,14 @@ prof_lookup(prof_bt_t *bt)
|
||||
idalloc(ctx.v);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Acquire ctx's lock before releasing bt2ctx_mtx, in order to
|
||||
* avoid a race condition with prof_ctx_destroy().
|
||||
*/
|
||||
malloc_mutex_lock(&ctx.p->lock);
|
||||
/*
|
||||
* Artificially raise curobjs, in order to avoid a race
|
||||
* condition with prof_ctx_merge()/prof_ctx_destroy().
|
||||
*/
|
||||
ctx.p->cnt_merged.curobjs++;
|
||||
new_ctx = true;
|
||||
} else
|
||||
new_ctx = false;
|
||||
prof_leave();
|
||||
|
||||
/* Link a prof_thd_cnt_t into ctx for this thread. */
|
||||
@@ -496,8 +500,14 @@ prof_lookup(prof_bt_t *bt)
|
||||
opt_lg_prof_tcmax));
|
||||
/* Allocate and partially initialize a new cnt. */
|
||||
ret.v = imalloc(sizeof(prof_thr_cnt_t));
|
||||
if (ret.p == NULL)
|
||||
if (ret.p == NULL) {
|
||||
if (new_ctx) {
|
||||
malloc_mutex_lock(&ctx.p->lock);
|
||||
ctx.p->cnt_merged.curobjs--;
|
||||
malloc_mutex_unlock(&ctx.p->lock);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
ql_elm_new(ret.p, cnts_link);
|
||||
ql_elm_new(ret.p, lru_link);
|
||||
}
|
||||
@@ -506,11 +516,19 @@ prof_lookup(prof_bt_t *bt)
|
||||
ret.p->epoch = 0;
|
||||
memset(&ret.p->cnts, 0, sizeof(prof_cnt_t));
|
||||
if (ckh_insert(&prof_tdata->bt2cnt, btkey.v, ret.v)) {
|
||||
if (new_ctx) {
|
||||
malloc_mutex_lock(&ctx.p->lock);
|
||||
ctx.p->cnt_merged.curobjs--;
|
||||
malloc_mutex_unlock(&ctx.p->lock);
|
||||
}
|
||||
idalloc(ret.v);
|
||||
return (NULL);
|
||||
}
|
||||
ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link);
|
||||
malloc_mutex_lock(&ctx.p->lock);
|
||||
ql_tail_insert(&ctx.p->cnts_ql, ret.p, cnts_link);
|
||||
if (new_ctx)
|
||||
ctx.p->cnt_merged.curobjs--;
|
||||
malloc_mutex_unlock(&ctx.p->lock);
|
||||
} else {
|
||||
/* Move ret to the front of the LRU. */
|
||||
@@ -625,11 +643,14 @@ prof_ctx_destroy(prof_ctx_t *ctx)
|
||||
/*
|
||||
* Check that ctx is still unused by any thread cache before destroying
|
||||
* it. prof_lookup() interlocks bt2ctx_mtx and ctx->lock in order to
|
||||
* avoid a race condition with this function.
|
||||
* avoid a race condition with this function, and prof_ctx_merge()
|
||||
* artificially raises ctx->cnt_merged.curobjs in order to avoid a race
|
||||
* between the main body of prof_ctx_merge() and entry into this
|
||||
* function.
|
||||
*/
|
||||
prof_enter();
|
||||
malloc_mutex_lock(&ctx->lock);
|
||||
if (ql_first(&ctx->cnts_ql) == NULL && ctx->cnt_merged.curobjs == 0) {
|
||||
if (ql_first(&ctx->cnts_ql) == NULL && ctx->cnt_merged.curobjs == 1) {
|
||||
assert(ctx->cnt_merged.curbytes == 0);
|
||||
assert(ctx->cnt_merged.accumobjs == 0);
|
||||
assert(ctx->cnt_merged.accumbytes == 0);
|
||||
@@ -642,6 +663,8 @@ prof_ctx_destroy(prof_ctx_t *ctx)
|
||||
malloc_mutex_destroy(&ctx->lock);
|
||||
idalloc(ctx);
|
||||
} else {
|
||||
/* Compensate for increment in prof_ctx_merge(). */
|
||||
ctx->cnt_merged.curobjs--;
|
||||
malloc_mutex_unlock(&ctx->lock);
|
||||
prof_leave();
|
||||
}
|
||||
@@ -660,9 +683,23 @@ prof_ctx_merge(prof_ctx_t *ctx, prof_thr_cnt_t *cnt)
|
||||
ctx->cnt_merged.accumbytes += cnt->cnts.accumbytes;
|
||||
ql_remove(&ctx->cnts_ql, cnt, cnts_link);
|
||||
if (opt_prof_accum == false && ql_first(&ctx->cnts_ql) == NULL &&
|
||||
ctx->cnt_merged.curobjs == 0)
|
||||
ctx->cnt_merged.curobjs == 0) {
|
||||
/*
|
||||
* Artificially raise ctx->cnt_merged.curobjs in order to keep
|
||||
* another thread from winning the race to destroy ctx while
|
||||
* this one has ctx->lock dropped. Without this, it would be
|
||||
* possible for another thread to:
|
||||
*
|
||||
* 1) Sample an allocation associated with ctx.
|
||||
* 2) Deallocate the sampled object.
|
||||
* 3) Successfully prof_ctx_destroy(ctx).
|
||||
*
|
||||
* The result would be that ctx no longer exists by the time
|
||||
* this thread accesses it in prof_ctx_destroy().
|
||||
*/
|
||||
ctx->cnt_merged.curobjs++;
|
||||
destroy = true;
|
||||
else
|
||||
} else
|
||||
destroy = false;
|
||||
malloc_mutex_unlock(&ctx->lock);
|
||||
if (destroy)
|
||||
|
||||
@@ -16,6 +16,7 @@ thread_start(void *arg)
|
||||
int err;
|
||||
void *p;
|
||||
uint64_t a0, a1, d0, d1;
|
||||
uint64_t *ap0, *ap1, *dp0, *dp1;
|
||||
size_t sz, usize;
|
||||
|
||||
sz = sizeof(a0);
|
||||
@@ -31,6 +32,20 @@ thread_start(void *arg)
|
||||
strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
sz = sizeof(ap0);
|
||||
if ((err = JEMALLOC_P(mallctl)("thread.allocatedp", &ap0, &sz, NULL,
|
||||
0))) {
|
||||
if (err == ENOENT) {
|
||||
#ifdef JEMALLOC_STATS
|
||||
assert(false);
|
||||
#endif
|
||||
goto RETURN;
|
||||
}
|
||||
fprintf(stderr, "%s(): Error in mallctl(): %s\n", __func__,
|
||||
strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
assert(*ap0 == a0);
|
||||
|
||||
sz = sizeof(d0);
|
||||
if ((err = JEMALLOC_P(mallctl)("thread.deallocated", &d0, &sz, NULL,
|
||||
@@ -45,6 +60,20 @@ thread_start(void *arg)
|
||||
strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
sz = sizeof(dp0);
|
||||
if ((err = JEMALLOC_P(mallctl)("thread.deallocatedp", &dp0, &sz, NULL,
|
||||
0))) {
|
||||
if (err == ENOENT) {
|
||||
#ifdef JEMALLOC_STATS
|
||||
assert(false);
|
||||
#endif
|
||||
goto RETURN;
|
||||
}
|
||||
fprintf(stderr, "%s(): Error in mallctl(): %s\n", __func__,
|
||||
strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
assert(*dp0 == d0);
|
||||
|
||||
p = JEMALLOC_P(malloc)(1);
|
||||
if (p == NULL) {
|
||||
@@ -54,6 +83,10 @@ thread_start(void *arg)
|
||||
|
||||
sz = sizeof(a1);
|
||||
JEMALLOC_P(mallctl)("thread.allocated", &a1, &sz, NULL, 0);
|
||||
sz = sizeof(ap1);
|
||||
JEMALLOC_P(mallctl)("thread.allocatedp", &ap1, &sz, NULL, 0);
|
||||
assert(*ap1 == a1);
|
||||
assert(ap0 == ap1);
|
||||
|
||||
usize = JEMALLOC_P(malloc_usable_size)(p);
|
||||
assert(a0 + usize <= a1);
|
||||
@@ -62,6 +95,10 @@ thread_start(void *arg)
|
||||
|
||||
sz = sizeof(d1);
|
||||
JEMALLOC_P(mallctl)("thread.deallocated", &d1, &sz, NULL, 0);
|
||||
sz = sizeof(dp1);
|
||||
JEMALLOC_P(mallctl)("thread.deallocatedp", &dp1, &sz, NULL, 0);
|
||||
assert(*dp1 == d1);
|
||||
assert(dp0 == dp1);
|
||||
|
||||
assert(d0 + usize <= d1);
|
||||
|
||||
|
||||
67
jemalloc/test/mremap.c
Normal file
67
jemalloc/test/mremap.c
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#define JEMALLOC_MANGLE
|
||||
#include "jemalloc_test.h"
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int ret, err;
|
||||
size_t sz, lg_chunk, chunksize, i;
|
||||
char *p, *q;
|
||||
|
||||
fprintf(stderr, "Test begin\n");
|
||||
|
||||
sz = sizeof(lg_chunk);
|
||||
if ((err = JEMALLOC_P(mallctl)("opt.lg_chunk", &lg_chunk, &sz, NULL,
|
||||
0))) {
|
||||
assert(err != ENOENT);
|
||||
fprintf(stderr, "%s(): Error in mallctl(): %s\n", __func__,
|
||||
strerror(err));
|
||||
ret = 1;
|
||||
goto RETURN;
|
||||
}
|
||||
chunksize = ((size_t)1U) << lg_chunk;
|
||||
|
||||
p = (char *)malloc(chunksize);
|
||||
if (p == NULL) {
|
||||
fprintf(stderr, "malloc(%zu) --> %p\n", chunksize, p);
|
||||
ret = 1;
|
||||
goto RETURN;
|
||||
}
|
||||
memset(p, 'a', chunksize);
|
||||
|
||||
q = (char *)realloc(p, chunksize * 2);
|
||||
if (q == NULL) {
|
||||
fprintf(stderr, "realloc(%p, %zu) --> %p\n", p, chunksize * 2,
|
||||
q);
|
||||
ret = 1;
|
||||
goto RETURN;
|
||||
}
|
||||
for (i = 0; i < chunksize; i++) {
|
||||
assert(q[i] == 'a');
|
||||
}
|
||||
|
||||
p = q;
|
||||
|
||||
q = (char *)realloc(p, chunksize);
|
||||
if (q == NULL) {
|
||||
fprintf(stderr, "realloc(%p, %zu) --> %p\n", p, chunksize, q);
|
||||
ret = 1;
|
||||
goto RETURN;
|
||||
}
|
||||
for (i = 0; i < chunksize; i++) {
|
||||
assert(q[i] == 'a');
|
||||
}
|
||||
|
||||
free(q);
|
||||
|
||||
ret = 0;
|
||||
RETURN:
|
||||
fprintf(stderr, "Test end\n");
|
||||
return (ret);
|
||||
}
|
||||
2
jemalloc/test/mremap.exp
Normal file
2
jemalloc/test/mremap.exp
Normal file
@@ -0,0 +1,2 @@
|
||||
Test begin
|
||||
Test end
|
||||
Reference in New Issue
Block a user