mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-23 13:13:06 +00:00
Compare commits
119 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1f7635731 | ||
|
|
2d1bb8980f | ||
|
|
145f3cd173 | ||
|
|
e1b2970d28 | ||
|
|
34a7e37a71 | ||
|
|
a05d4da4d8 | ||
|
|
e98a620c59 | ||
|
|
fc11f3cb84 | ||
|
|
949a27fc32 | ||
|
|
62f2d84e7a | ||
|
|
e7ca53bac2 | ||
|
|
0d6a472db9 | ||
|
|
3ea838d2a2 | ||
|
|
8e3fb7f417 | ||
|
|
2a24dc2476 | ||
|
|
6468dd52f3 | ||
|
|
8f61fdedb9 | ||
|
|
84ae603577 | ||
|
|
72c587a411 | ||
|
|
87004d238c | ||
|
|
2379479225 | ||
|
|
6a71d37a75 | ||
|
|
5c77af98b1 | ||
|
|
45f83a2ac6 | ||
|
|
ded4f38ffd | ||
|
|
1aeea0f391 | ||
|
|
a2af09f025 | ||
|
|
b9408d77a6 | ||
|
|
2cdf07aba9 | ||
|
|
e916d55ba1 | ||
|
|
092d760817 | ||
|
|
b4486dce24 | ||
|
|
0110fa8451 | ||
|
|
b0f56583b7 | ||
|
|
7b8e74f48f | ||
|
|
5d6cb6eb66 | ||
|
|
a4e83e8593 | ||
|
|
9bef119b42 | ||
|
|
8019f4c21c | ||
|
|
23f04ef9b7 | ||
|
|
28b7e42e44 | ||
|
|
77635bf532 | ||
|
|
cb3ad659f0 | ||
|
|
213667fe26 | ||
|
|
32896a902b | ||
|
|
e9012630ac | ||
|
|
dd3ed23aea | ||
|
|
1ceae2f8cb | ||
|
|
62de7680ca | ||
|
|
6c56e194b0 | ||
|
|
eca3bc0131 | ||
|
|
da206df10b | ||
|
|
3f2b8d9cfa | ||
|
|
a99e0fa2d2 | ||
|
|
31db315f17 | ||
|
|
07ee4c5ff4 | ||
|
|
f19bedb04c | ||
|
|
b599b32280 | ||
|
|
4752a54eeb | ||
|
|
1d57c03e33 | ||
|
|
c443b67561 | ||
|
|
35a108c809 | ||
|
|
e46f8f97bc | ||
|
|
35799a5030 | ||
|
|
ed84764a2a | ||
|
|
b99c72f3d2 | ||
|
|
eaecaad8ea | ||
|
|
2c53faf352 | ||
|
|
e7d6779918 | ||
|
|
875ff15e6a | ||
|
|
1eb801bcad | ||
|
|
dc553d52d8 | ||
|
|
5569b4a42c | ||
|
|
962a2979e3 | ||
|
|
e2bcf037d4 | ||
|
|
9737685943 | ||
|
|
a2539fab95 | ||
|
|
d419bb09ef | ||
|
|
a14712b4b8 | ||
|
|
45a5bf6772 | ||
|
|
94e7ffa979 | ||
|
|
b732c395b7 | ||
|
|
5d8db15db9 | ||
|
|
f193fd80cf | ||
|
|
1abb49f09d | ||
|
|
bcd5424b1c | ||
|
|
c19b48fe73 | ||
|
|
af33e9a597 | ||
|
|
79647fe465 | ||
|
|
3bb044c807 | ||
|
|
43d4d7c373 | ||
|
|
92009b19d6 | ||
|
|
15da5f5d9d | ||
|
|
b54c0c2925 | ||
|
|
c128167bca | ||
|
|
4b52518398 | ||
|
|
1d42a99027 | ||
|
|
8701bc7079 | ||
|
|
b770d2da1d | ||
|
|
3573fb93ce | ||
|
|
5acef864f2 | ||
|
|
50a865e15a | ||
|
|
57cddffca6 | ||
|
|
11b5da7533 | ||
|
|
38a96f07ac | ||
|
|
d1207f0d37 | ||
|
|
a6a8e40f7d | ||
|
|
57ed894f8a | ||
|
|
9ebbfca93f | ||
|
|
3de0353352 | ||
|
|
5271b673b2 | ||
|
|
fa09fe798a | ||
|
|
20cd2de5ef | ||
|
|
a7fdcc8b09 | ||
|
|
c7d5298027 | ||
|
|
9de0094e6e | ||
|
|
05a9e4ac65 | ||
|
|
48384dc2d8 | ||
|
|
09d7bdb314 |
28
.appveyor.yml
Normal file
28
.appveyor.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
version: '{build}'
|
||||||
|
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- MSYSTEM: MINGW64
|
||||||
|
CPU: x86_64
|
||||||
|
MSVC: amd64
|
||||||
|
- MSYSTEM: MINGW32
|
||||||
|
CPU: i686
|
||||||
|
MSVC: x86
|
||||||
|
- MSYSTEM: MINGW64
|
||||||
|
CPU: x86_64
|
||||||
|
- MSYSTEM: MINGW32
|
||||||
|
CPU: i686
|
||||||
|
|
||||||
|
install:
|
||||||
|
- set PATH=c:\msys64\%MSYSTEM%\bin;c:\msys64\usr\bin;%PATH%
|
||||||
|
- if defined MSVC call "c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %MSVC%
|
||||||
|
- if defined MSVC pacman --noconfirm -Rsc mingw-w64-%CPU%-gcc gcc
|
||||||
|
- pacman --noconfirm -Suy mingw-w64-%CPU%-make
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- bash -c "autoconf"
|
||||||
|
- bash -c "./configure"
|
||||||
|
- mingw32-make -j3
|
||||||
|
- file lib/jemalloc.dll
|
||||||
|
- mingw32-make -j3 tests
|
||||||
|
- mingw32-make -k check
|
||||||
29
.travis.yml
Normal file
29
.travis.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
language: c
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
env:
|
||||||
|
- EXTRA_FLAGS=-m32
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- gcc-multilib
|
||||||
|
- os: osx
|
||||||
|
compiler: clang
|
||||||
|
- os: osx
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- EXTRA_FLAGS=-m32
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- autoconf
|
||||||
|
- ./configure${EXTRA_FLAGS:+ CC="$CC $EXTRA_FLAGS"}
|
||||||
|
- make -j3
|
||||||
|
- make -j3 tests
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make check
|
||||||
93
ChangeLog
93
ChangeLog
@@ -4,11 +4,102 @@ brevity. Much more detail can be found in the git revision history:
|
|||||||
|
|
||||||
https://github.com/jemalloc/jemalloc
|
https://github.com/jemalloc/jemalloc
|
||||||
|
|
||||||
|
* 4.4.0 (December 3, 2016)
|
||||||
|
|
||||||
|
New features:
|
||||||
|
- Add configure support for *-*-linux-android. (@cferris1000, @jasone)
|
||||||
|
- Add the --disable-syscall configure option, for use on systems that place
|
||||||
|
security-motivated limitations on syscall(2). (@jasone)
|
||||||
|
- Add support for Debian GNU/kFreeBSD. (@thesam)
|
||||||
|
|
||||||
|
Optimizations:
|
||||||
|
- Add extent serial numbers and use them where appropriate as a sort key that
|
||||||
|
is higher priority than address, so that the allocation policy prefers older
|
||||||
|
extents. This tends to improve locality (decrease fragmentation) when
|
||||||
|
memory grows downward. (@jasone)
|
||||||
|
- Refactor madvise(2) configuration so that MADV_FREE is detected and utilized
|
||||||
|
on Linux 4.5 and newer. (@jasone)
|
||||||
|
- Mark partially purged arena chunks as non-huge-page. This improves
|
||||||
|
interaction with Linux's transparent huge page functionality. (@jasone)
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
- Fix size class computations for edge conditions involving extremely large
|
||||||
|
allocations. This regression was first released in 4.0.0. (@jasone,
|
||||||
|
@ingvarha)
|
||||||
|
- Remove overly restrictive assertions related to the cactive statistic. This
|
||||||
|
regression was first released in 4.1.0. (@jasone)
|
||||||
|
- Implement a more reliable detection scheme for os_unfair_lock on macOS.
|
||||||
|
(@jszakmeister)
|
||||||
|
|
||||||
|
* 4.3.1 (November 7, 2016)
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
- Fix a severe virtual memory leak. This regression was first released in
|
||||||
|
4.3.0. (@interwq, @jasone)
|
||||||
|
- Refactor atomic and prng APIs to restore support for 32-bit platforms that
|
||||||
|
use pre-C11 toolchains, e.g. FreeBSD's mips. (@jasone)
|
||||||
|
|
||||||
|
* 4.3.0 (November 4, 2016)
|
||||||
|
|
||||||
|
This is the first release that passes the test suite for multiple Windows
|
||||||
|
configurations, thanks in large part to @glandium setting up continuous
|
||||||
|
integration via AppVeyor (and Travis CI for Linux and OS X).
|
||||||
|
|
||||||
|
New features:
|
||||||
|
- Add "J" (JSON) support to malloc_stats_print(). (@jasone)
|
||||||
|
- Add Cray compiler support. (@ronawho)
|
||||||
|
|
||||||
|
Optimizations:
|
||||||
|
- Add/use adaptive spinning for bootstrapping and radix tree node
|
||||||
|
initialization. (@jasone)
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
- Fix large allocation to search starting in the optimal size class heap,
|
||||||
|
which can substantially reduce virtual memory churn and fragmentation. This
|
||||||
|
regression was first released in 4.0.0. (@mjp41, @jasone)
|
||||||
|
- Fix stats.arenas.<i>.nthreads accounting. (@interwq)
|
||||||
|
- Fix and simplify decay-based purging. (@jasone)
|
||||||
|
- Make DSS (sbrk(2)-related) operations lockless, which resolves potential
|
||||||
|
deadlocks during thread exit. (@jasone)
|
||||||
|
- Fix over-sized allocation of radix tree leaf nodes. (@mjp41, @ogaun,
|
||||||
|
@jasone)
|
||||||
|
- Fix over-sized allocation of arena_t (plus associated stats) data
|
||||||
|
structures. (@jasone, @interwq)
|
||||||
|
- Fix EXTRA_CFLAGS to not affect configuration. (@jasone)
|
||||||
|
- Fix a Valgrind integration bug. (@ronawho)
|
||||||
|
- Disallow 0x5a junk filling when running in Valgrind. (@jasone)
|
||||||
|
- Fix a file descriptor leak on Linux. This regression was first released in
|
||||||
|
4.2.0. (@vsarunas, @jasone)
|
||||||
|
- Fix static linking of jemalloc with glibc. (@djwatson)
|
||||||
|
- Use syscall(2) rather than {open,read,close}(2) during boot on Linux. This
|
||||||
|
works around other libraries' system call wrappers performing reentrant
|
||||||
|
allocation. (@kspinka, @Whissi, @jasone)
|
||||||
|
- Fix OS X default zone replacement to work with OS X 10.12. (@glandium,
|
||||||
|
@jasone)
|
||||||
|
- Fix cached memory management to avoid needless commit/decommit operations
|
||||||
|
during purging, which resolves permanent virtual memory map fragmentation
|
||||||
|
issues on Windows. (@mjp41, @jasone)
|
||||||
|
- Fix TSD fetches to avoid (recursive) allocation. This is relevant to
|
||||||
|
non-TLS and Windows configurations. (@jasone)
|
||||||
|
- Fix malloc_conf overriding to work on Windows. (@jasone)
|
||||||
|
- Forcibly disable lazy-lock on Windows (was forcibly *enabled*). (@jasone)
|
||||||
|
|
||||||
|
* 4.2.1 (June 8, 2016)
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
- Fix bootstrapping issues for configurations that require allocation during
|
||||||
|
tsd initialization (e.g. --disable-tls). (@cferris1000, @jasone)
|
||||||
|
- Fix gettimeofday() version of nstime_update(). (@ronawho)
|
||||||
|
- Fix Valgrind regressions in calloc() and chunk_alloc_wrapper(). (@ronawho)
|
||||||
|
- Fix potential VM map fragmentation regression. (@jasone)
|
||||||
|
- Fix opt_zero-triggered in-place huge reallocation zeroing. (@jasone)
|
||||||
|
- Fix heap profiling context leaks in reallocation edge cases. (@jasone)
|
||||||
|
|
||||||
* 4.2.0 (May 12, 2016)
|
* 4.2.0 (May 12, 2016)
|
||||||
|
|
||||||
New features:
|
New features:
|
||||||
- Add the arena.<i>.reset mallctl, which makes it possible to discard all of
|
- Add the arena.<i>.reset mallctl, which makes it possible to discard all of
|
||||||
an arena's allocations in a single operation. (@jasone@)
|
an arena's allocations in a single operation. (@jasone)
|
||||||
- Add the stats.retained and stats.arenas.<i>.retained statistics. (@jasone)
|
- Add the stats.retained and stats.arenas.<i>.retained statistics. (@jasone)
|
||||||
- Add the --with-version configure option. (@jasone)
|
- Add the --with-version configure option. (@jasone)
|
||||||
- Support --with-lg-page values larger than actual page size. (@jasone)
|
- Support --with-lg-page values larger than actual page size. (@jasone)
|
||||||
|
|||||||
14
INSTALL
14
INSTALL
@@ -206,6 +206,11 @@ any of the following arguments (not a definitive list) to 'configure':
|
|||||||
most extreme case increases physical memory usage for the 16 KiB size class
|
most extreme case increases physical memory usage for the 16 KiB size class
|
||||||
to 20 KiB.
|
to 20 KiB.
|
||||||
|
|
||||||
|
--disable-syscall
|
||||||
|
Disable use of syscall(2) rather than {open,read,write,close}(2). This is
|
||||||
|
intended as a workaround for systems that place security limitations on
|
||||||
|
syscall(2).
|
||||||
|
|
||||||
--with-xslroot=<path>
|
--with-xslroot=<path>
|
||||||
Specify where to find DocBook XSL stylesheets when building the
|
Specify where to find DocBook XSL stylesheets when building the
|
||||||
documentation.
|
documentation.
|
||||||
@@ -327,6 +332,15 @@ LDFLAGS="?"
|
|||||||
PATH="?"
|
PATH="?"
|
||||||
'configure' uses this to find programs.
|
'configure' uses this to find programs.
|
||||||
|
|
||||||
|
In some cases it may be necessary to work around configuration results that do
|
||||||
|
not match reality. For example, Linux 4.5 added support for the MADV_FREE flag
|
||||||
|
to madvise(2), which can cause problems if building on a host with MADV_FREE
|
||||||
|
support and deploying to a target without. To work around this, use a cache
|
||||||
|
file to override the relevant configuration variable defined in configure.ac,
|
||||||
|
e.g.:
|
||||||
|
|
||||||
|
echo "je_cv_madv_free=no" > config.cache && ./configure -C
|
||||||
|
|
||||||
=== Advanced compilation =======================================================
|
=== Advanced compilation =======================================================
|
||||||
|
|
||||||
To build only parts of jemalloc, use the following targets:
|
To build only parts of jemalloc, use the following targets:
|
||||||
|
|||||||
65
Makefile.in
65
Makefile.in
@@ -24,7 +24,8 @@ abs_objroot := @abs_objroot@
|
|||||||
|
|
||||||
# Build parameters.
|
# Build parameters.
|
||||||
CPPFLAGS := @CPPFLAGS@ -I$(srcroot)include -I$(objroot)include
|
CPPFLAGS := @CPPFLAGS@ -I$(srcroot)include -I$(objroot)include
|
||||||
CFLAGS := @CFLAGS@
|
EXTRA_CFLAGS := @EXTRA_CFLAGS@
|
||||||
|
CFLAGS := @CFLAGS@ $(EXTRA_CFLAGS)
|
||||||
LDFLAGS := @LDFLAGS@
|
LDFLAGS := @LDFLAGS@
|
||||||
EXTRA_LDFLAGS := @EXTRA_LDFLAGS@
|
EXTRA_LDFLAGS := @EXTRA_LDFLAGS@
|
||||||
LIBS := @LIBS@
|
LIBS := @LIBS@
|
||||||
@@ -52,15 +53,19 @@ enable_prof := @enable_prof@
|
|||||||
enable_valgrind := @enable_valgrind@
|
enable_valgrind := @enable_valgrind@
|
||||||
enable_zone_allocator := @enable_zone_allocator@
|
enable_zone_allocator := @enable_zone_allocator@
|
||||||
MALLOC_CONF := @JEMALLOC_CPREFIX@MALLOC_CONF
|
MALLOC_CONF := @JEMALLOC_CPREFIX@MALLOC_CONF
|
||||||
|
link_whole_archive := @link_whole_archive@
|
||||||
DSO_LDFLAGS = @DSO_LDFLAGS@
|
DSO_LDFLAGS = @DSO_LDFLAGS@
|
||||||
SOREV = @SOREV@
|
SOREV = @SOREV@
|
||||||
PIC_CFLAGS = @PIC_CFLAGS@
|
PIC_CFLAGS = @PIC_CFLAGS@
|
||||||
CTARGET = @CTARGET@
|
CTARGET = @CTARGET@
|
||||||
LDTARGET = @LDTARGET@
|
LDTARGET = @LDTARGET@
|
||||||
|
TEST_LD_MODE = @TEST_LD_MODE@
|
||||||
MKLIB = @MKLIB@
|
MKLIB = @MKLIB@
|
||||||
AR = @AR@
|
AR = @AR@
|
||||||
ARFLAGS = @ARFLAGS@
|
ARFLAGS = @ARFLAGS@
|
||||||
CC_MM = @CC_MM@
|
CC_MM = @CC_MM@
|
||||||
|
LM := @LM@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
|
||||||
ifeq (macho, $(ABI))
|
ifeq (macho, $(ABI))
|
||||||
TEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH="$(objroot)lib"
|
TEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH="$(objroot)lib"
|
||||||
@@ -99,6 +104,7 @@ C_SRCS := $(srcroot)src/jemalloc.c \
|
|||||||
$(srcroot)src/quarantine.c \
|
$(srcroot)src/quarantine.c \
|
||||||
$(srcroot)src/rtree.c \
|
$(srcroot)src/rtree.c \
|
||||||
$(srcroot)src/stats.c \
|
$(srcroot)src/stats.c \
|
||||||
|
$(srcroot)src/spin.c \
|
||||||
$(srcroot)src/tcache.c \
|
$(srcroot)src/tcache.c \
|
||||||
$(srcroot)src/ticker.c \
|
$(srcroot)src/ticker.c \
|
||||||
$(srcroot)src/tsd.c \
|
$(srcroot)src/tsd.c \
|
||||||
@@ -122,6 +128,11 @@ DSOS := $(objroot)lib/$(LIBJEMALLOC).$(SOREV)
|
|||||||
ifneq ($(SOREV),$(SO))
|
ifneq ($(SOREV),$(SO))
|
||||||
DSOS += $(objroot)lib/$(LIBJEMALLOC).$(SO)
|
DSOS += $(objroot)lib/$(LIBJEMALLOC).$(SO)
|
||||||
endif
|
endif
|
||||||
|
ifeq (1, $(link_whole_archive))
|
||||||
|
LJEMALLOC := -Wl,--whole-archive -L$(objroot)lib -l$(LIBJEMALLOC) -Wl,--no-whole-archive
|
||||||
|
else
|
||||||
|
LJEMALLOC := $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)
|
||||||
|
endif
|
||||||
PC := $(objroot)jemalloc.pc
|
PC := $(objroot)jemalloc.pc
|
||||||
MAN3 := $(objroot)doc/jemalloc$(install_suffix).3
|
MAN3 := $(objroot)doc/jemalloc$(install_suffix).3
|
||||||
DOCS_XML := $(objroot)doc/jemalloc$(install_suffix).xml
|
DOCS_XML := $(objroot)doc/jemalloc$(install_suffix).xml
|
||||||
@@ -133,7 +144,11 @@ C_TESTLIB_SRCS := $(srcroot)test/src/btalloc.c $(srcroot)test/src/btalloc_0.c \
|
|||||||
$(srcroot)test/src/mtx.c $(srcroot)test/src/mq.c \
|
$(srcroot)test/src/mtx.c $(srcroot)test/src/mq.c \
|
||||||
$(srcroot)test/src/SFMT.c $(srcroot)test/src/test.c \
|
$(srcroot)test/src/SFMT.c $(srcroot)test/src/test.c \
|
||||||
$(srcroot)test/src/thd.c $(srcroot)test/src/timer.c
|
$(srcroot)test/src/thd.c $(srcroot)test/src/timer.c
|
||||||
|
ifeq (1, $(link_whole_archive))
|
||||||
|
C_UTIL_INTEGRATION_SRCS :=
|
||||||
|
else
|
||||||
C_UTIL_INTEGRATION_SRCS := $(srcroot)src/nstime.c $(srcroot)src/util.c
|
C_UTIL_INTEGRATION_SRCS := $(srcroot)src/nstime.c $(srcroot)src/util.c
|
||||||
|
endif
|
||||||
TESTS_UNIT := \
|
TESTS_UNIT := \
|
||||||
$(srcroot)test/unit/a0.c \
|
$(srcroot)test/unit/a0.c \
|
||||||
$(srcroot)test/unit/arena_reset.c \
|
$(srcroot)test/unit/arena_reset.c \
|
||||||
@@ -151,6 +166,8 @@ TESTS_UNIT := \
|
|||||||
$(srcroot)test/unit/math.c \
|
$(srcroot)test/unit/math.c \
|
||||||
$(srcroot)test/unit/mq.c \
|
$(srcroot)test/unit/mq.c \
|
||||||
$(srcroot)test/unit/mtx.c \
|
$(srcroot)test/unit/mtx.c \
|
||||||
|
$(srcroot)test/unit/pack.c \
|
||||||
|
$(srcroot)test/unit/pages.c \
|
||||||
$(srcroot)test/unit/ph.c \
|
$(srcroot)test/unit/ph.c \
|
||||||
$(srcroot)test/unit/prng.c \
|
$(srcroot)test/unit/prng.c \
|
||||||
$(srcroot)test/unit/prof_accum.c \
|
$(srcroot)test/unit/prof_accum.c \
|
||||||
@@ -295,69 +312,69 @@ $(STATIC_LIBS):
|
|||||||
|
|
||||||
$(objroot)test/unit/%$(EXE): $(objroot)test/unit/%.$(O) $(TESTS_UNIT_LINK_OBJS) $(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)
|
@mkdir -p $(@D)
|
||||||
$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS)
|
$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LDFLAGS) $(filter-out -lm,$(LIBS)) $(LM) $(EXTRA_LDFLAGS)
|
||||||
|
|
||||||
$(objroot)test/integration/%$(EXE): $(objroot)test/integration/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)
|
$(objroot)test/integration/%$(EXE): $(objroot)test/integration/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(filter -lpthread,$(LIBS))) -lm $(EXTRA_LDFLAGS)
|
$(CC) $(TEST_LD_MODE) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LJEMALLOC) $(LDFLAGS) $(filter-out -lm,$(filter -lrt -lpthread,$(LIBS))) $(LM) $(EXTRA_LDFLAGS)
|
||||||
|
|
||||||
$(objroot)test/stress/%$(EXE): $(objroot)test/stress/%.$(O) $(C_JET_OBJS) $(C_TESTLIB_STRESS_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)
|
$(objroot)test/stress/%$(EXE): $(objroot)test/stress/%.$(O) $(C_JET_OBJS) $(C_TESTLIB_STRESS_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS)
|
$(CC) $(TEST_LD_MODE) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(LIBS)) $(LM) $(EXTRA_LDFLAGS)
|
||||||
|
|
||||||
build_lib_shared: $(DSOS)
|
build_lib_shared: $(DSOS)
|
||||||
build_lib_static: $(STATIC_LIBS)
|
build_lib_static: $(STATIC_LIBS)
|
||||||
build_lib: build_lib_shared build_lib_static
|
build_lib: build_lib_shared build_lib_static
|
||||||
|
|
||||||
install_bin:
|
install_bin:
|
||||||
install -d $(BINDIR)
|
$(INSTALL) -d $(BINDIR)
|
||||||
@for b in $(BINS); do \
|
@for b in $(BINS); do \
|
||||||
echo "install -m 755 $$b $(BINDIR)"; \
|
echo "$(INSTALL) -m 755 $$b $(BINDIR)"; \
|
||||||
install -m 755 $$b $(BINDIR); \
|
$(INSTALL) -m 755 $$b $(BINDIR); \
|
||||||
done
|
done
|
||||||
|
|
||||||
install_include:
|
install_include:
|
||||||
install -d $(INCLUDEDIR)/jemalloc
|
$(INSTALL) -d $(INCLUDEDIR)/jemalloc
|
||||||
@for h in $(C_HDRS); do \
|
@for h in $(C_HDRS); do \
|
||||||
echo "install -m 644 $$h $(INCLUDEDIR)/jemalloc"; \
|
echo "$(INSTALL) -m 644 $$h $(INCLUDEDIR)/jemalloc"; \
|
||||||
install -m 644 $$h $(INCLUDEDIR)/jemalloc; \
|
$(INSTALL) -m 644 $$h $(INCLUDEDIR)/jemalloc; \
|
||||||
done
|
done
|
||||||
|
|
||||||
install_lib_shared: $(DSOS)
|
install_lib_shared: $(DSOS)
|
||||||
install -d $(LIBDIR)
|
$(INSTALL) -d $(LIBDIR)
|
||||||
install -m 755 $(objroot)lib/$(LIBJEMALLOC).$(SOREV) $(LIBDIR)
|
$(INSTALL) -m 755 $(objroot)lib/$(LIBJEMALLOC).$(SOREV) $(LIBDIR)
|
||||||
ifneq ($(SOREV),$(SO))
|
ifneq ($(SOREV),$(SO))
|
||||||
ln -sf $(LIBJEMALLOC).$(SOREV) $(LIBDIR)/$(LIBJEMALLOC).$(SO)
|
ln -sf $(LIBJEMALLOC).$(SOREV) $(LIBDIR)/$(LIBJEMALLOC).$(SO)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
install_lib_static: $(STATIC_LIBS)
|
install_lib_static: $(STATIC_LIBS)
|
||||||
install -d $(LIBDIR)
|
$(INSTALL) -d $(LIBDIR)
|
||||||
@for l in $(STATIC_LIBS); do \
|
@for l in $(STATIC_LIBS); do \
|
||||||
echo "install -m 755 $$l $(LIBDIR)"; \
|
echo "$(INSTALL) -m 755 $$l $(LIBDIR)"; \
|
||||||
install -m 755 $$l $(LIBDIR); \
|
$(INSTALL) -m 755 $$l $(LIBDIR); \
|
||||||
done
|
done
|
||||||
|
|
||||||
install_lib_pc: $(PC)
|
install_lib_pc: $(PC)
|
||||||
install -d $(LIBDIR)/pkgconfig
|
$(INSTALL) -d $(LIBDIR)/pkgconfig
|
||||||
@for l in $(PC); do \
|
@for l in $(PC); do \
|
||||||
echo "install -m 644 $$l $(LIBDIR)/pkgconfig"; \
|
echo "$(INSTALL) -m 644 $$l $(LIBDIR)/pkgconfig"; \
|
||||||
install -m 644 $$l $(LIBDIR)/pkgconfig; \
|
$(INSTALL) -m 644 $$l $(LIBDIR)/pkgconfig; \
|
||||||
done
|
done
|
||||||
|
|
||||||
install_lib: install_lib_shared install_lib_static install_lib_pc
|
install_lib: install_lib_shared install_lib_static install_lib_pc
|
||||||
|
|
||||||
install_doc_html:
|
install_doc_html:
|
||||||
install -d $(DATADIR)/doc/jemalloc$(install_suffix)
|
$(INSTALL) -d $(DATADIR)/doc/jemalloc$(install_suffix)
|
||||||
@for d in $(DOCS_HTML); do \
|
@for d in $(DOCS_HTML); do \
|
||||||
echo "install -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix)"; \
|
echo "$(INSTALL) -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix)"; \
|
||||||
install -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix); \
|
$(INSTALL) -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix); \
|
||||||
done
|
done
|
||||||
|
|
||||||
install_doc_man:
|
install_doc_man:
|
||||||
install -d $(MANDIR)/man3
|
$(INSTALL) -d $(MANDIR)/man3
|
||||||
@for d in $(DOCS_MAN3); do \
|
@for d in $(DOCS_MAN3); do \
|
||||||
echo "install -m 644 $$d $(MANDIR)/man3"; \
|
echo "$(INSTALL) -m 644 $$d $(MANDIR)/man3"; \
|
||||||
install -m 644 $$d $(MANDIR)/man3; \
|
$(INSTALL) -m 644 $$d $(MANDIR)/man3; \
|
||||||
done
|
done
|
||||||
|
|
||||||
install_doc: install_doc_html install_doc_man
|
install_doc: install_doc_html install_doc_man
|
||||||
|
|||||||
2
README
2
README
@@ -17,4 +17,4 @@ jemalloc.
|
|||||||
|
|
||||||
The ChangeLog file contains a brief summary of changes for each release.
|
The ChangeLog file contains a brief summary of changes for each release.
|
||||||
|
|
||||||
URL: http://www.canonware.com/jemalloc/
|
URL: http://jemalloc.net/
|
||||||
|
|||||||
174
build-aux/config.guess
vendored
174
build-aux/config.guess
vendored
@@ -1,8 +1,8 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Attempt to guess a canonical system name.
|
# Attempt to guess a canonical system name.
|
||||||
# Copyright 1992-2014 Free Software Foundation, Inc.
|
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
timestamp='2014-03-23'
|
timestamp='2016-10-02'
|
||||||
|
|
||||||
# This file is free software; you can redistribute it and/or modify it
|
# This file is free software; you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU General Public License as published by
|
# under the terms of the GNU General Public License as published by
|
||||||
@@ -24,12 +24,12 @@ timestamp='2014-03-23'
|
|||||||
# program. This Exception is an additional permission under section 7
|
# program. This Exception is an additional permission under section 7
|
||||||
# of the GNU General Public License, version 3 ("GPLv3").
|
# of the GNU General Public License, version 3 ("GPLv3").
|
||||||
#
|
#
|
||||||
# Originally written by Per Bothner.
|
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
|
||||||
#
|
#
|
||||||
# You can get the latest version of this script from:
|
# You can get the latest version of this script from:
|
||||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
|
||||||
#
|
#
|
||||||
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
|
# Please send patches to <config-patches@gnu.org>.
|
||||||
|
|
||||||
|
|
||||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||||
@@ -50,7 +50,7 @@ version="\
|
|||||||
GNU config.guess ($timestamp)
|
GNU config.guess ($timestamp)
|
||||||
|
|
||||||
Originally written by Per Bothner.
|
Originally written by Per Bothner.
|
||||||
Copyright 1992-2014 Free Software Foundation, Inc.
|
Copyright 1992-2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This is free software; see the source for copying conditions. There is NO
|
This is free software; see the source for copying conditions. There is NO
|
||||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||||
@@ -168,19 +168,29 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
# Note: NetBSD doesn't particularly care about the vendor
|
# Note: NetBSD doesn't particularly care about the vendor
|
||||||
# portion of the name. We always set it to "unknown".
|
# portion of the name. We always set it to "unknown".
|
||||||
sysctl="sysctl -n hw.machine_arch"
|
sysctl="sysctl -n hw.machine_arch"
|
||||||
UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
|
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
|
||||||
/usr/sbin/$sysctl 2>/dev/null || echo unknown)`
|
/sbin/$sysctl 2>/dev/null || \
|
||||||
|
/usr/sbin/$sysctl 2>/dev/null || \
|
||||||
|
echo unknown)`
|
||||||
case "${UNAME_MACHINE_ARCH}" in
|
case "${UNAME_MACHINE_ARCH}" in
|
||||||
armeb) machine=armeb-unknown ;;
|
armeb) machine=armeb-unknown ;;
|
||||||
arm*) machine=arm-unknown ;;
|
arm*) machine=arm-unknown ;;
|
||||||
sh3el) machine=shl-unknown ;;
|
sh3el) machine=shl-unknown ;;
|
||||||
sh3eb) machine=sh-unknown ;;
|
sh3eb) machine=sh-unknown ;;
|
||||||
sh5el) machine=sh5le-unknown ;;
|
sh5el) machine=sh5le-unknown ;;
|
||||||
|
earmv*)
|
||||||
|
arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
|
||||||
|
endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
|
||||||
|
machine=${arch}${endian}-unknown
|
||||||
|
;;
|
||||||
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
|
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
|
||||||
esac
|
esac
|
||||||
# The Operating System including object format, if it has switched
|
# The Operating System including object format, if it has switched
|
||||||
# to ELF recently, or will in the future.
|
# to ELF recently (or will in the future) and ABI.
|
||||||
case "${UNAME_MACHINE_ARCH}" in
|
case "${UNAME_MACHINE_ARCH}" in
|
||||||
|
earm*)
|
||||||
|
os=netbsdelf
|
||||||
|
;;
|
||||||
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||||
eval $set_cc_for_build
|
eval $set_cc_for_build
|
||||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||||
@@ -197,6 +207,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
os=netbsd
|
os=netbsd
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
# Determine ABI tags.
|
||||||
|
case "${UNAME_MACHINE_ARCH}" in
|
||||||
|
earm*)
|
||||||
|
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
|
||||||
|
abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
|
||||||
|
;;
|
||||||
|
esac
|
||||||
# The OS release
|
# The OS release
|
||||||
# Debian GNU/NetBSD machines have a different userland, and
|
# Debian GNU/NetBSD machines have a different userland, and
|
||||||
# thus, need a distinct triplet. However, they do not need
|
# thus, need a distinct triplet. However, they do not need
|
||||||
@@ -207,13 +224,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
release='-gnu'
|
release='-gnu'
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
||||||
# contains redundant information, the shorter form:
|
# contains redundant information, the shorter form:
|
||||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
|
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
|
||||||
echo "${machine}-${os}${release}"
|
echo "${machine}-${os}${release}${abi}"
|
||||||
exit ;;
|
exit ;;
|
||||||
*:Bitrig:*:*)
|
*:Bitrig:*:*)
|
||||||
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
|
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
|
||||||
@@ -223,6 +240,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
|
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
|
||||||
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
|
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
|
*:LibertyBSD:*:*)
|
||||||
|
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
|
||||||
|
echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
|
||||||
|
exit ;;
|
||||||
*:ekkoBSD:*:*)
|
*:ekkoBSD:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
|
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -235,6 +256,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
*:MirBSD:*:*)
|
*:MirBSD:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
|
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
|
*:Sortix:*:*)
|
||||||
|
echo ${UNAME_MACHINE}-unknown-sortix
|
||||||
|
exit ;;
|
||||||
alpha:OSF1:*:*)
|
alpha:OSF1:*:*)
|
||||||
case $UNAME_RELEASE in
|
case $UNAME_RELEASE in
|
||||||
*4.0)
|
*4.0)
|
||||||
@@ -251,42 +275,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
|
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
|
||||||
case "$ALPHA_CPU_TYPE" in
|
case "$ALPHA_CPU_TYPE" in
|
||||||
"EV4 (21064)")
|
"EV4 (21064)")
|
||||||
UNAME_MACHINE="alpha" ;;
|
UNAME_MACHINE=alpha ;;
|
||||||
"EV4.5 (21064)")
|
"EV4.5 (21064)")
|
||||||
UNAME_MACHINE="alpha" ;;
|
UNAME_MACHINE=alpha ;;
|
||||||
"LCA4 (21066/21068)")
|
"LCA4 (21066/21068)")
|
||||||
UNAME_MACHINE="alpha" ;;
|
UNAME_MACHINE=alpha ;;
|
||||||
"EV5 (21164)")
|
"EV5 (21164)")
|
||||||
UNAME_MACHINE="alphaev5" ;;
|
UNAME_MACHINE=alphaev5 ;;
|
||||||
"EV5.6 (21164A)")
|
"EV5.6 (21164A)")
|
||||||
UNAME_MACHINE="alphaev56" ;;
|
UNAME_MACHINE=alphaev56 ;;
|
||||||
"EV5.6 (21164PC)")
|
"EV5.6 (21164PC)")
|
||||||
UNAME_MACHINE="alphapca56" ;;
|
UNAME_MACHINE=alphapca56 ;;
|
||||||
"EV5.7 (21164PC)")
|
"EV5.7 (21164PC)")
|
||||||
UNAME_MACHINE="alphapca57" ;;
|
UNAME_MACHINE=alphapca57 ;;
|
||||||
"EV6 (21264)")
|
"EV6 (21264)")
|
||||||
UNAME_MACHINE="alphaev6" ;;
|
UNAME_MACHINE=alphaev6 ;;
|
||||||
"EV6.7 (21264A)")
|
"EV6.7 (21264A)")
|
||||||
UNAME_MACHINE="alphaev67" ;;
|
UNAME_MACHINE=alphaev67 ;;
|
||||||
"EV6.8CB (21264C)")
|
"EV6.8CB (21264C)")
|
||||||
UNAME_MACHINE="alphaev68" ;;
|
UNAME_MACHINE=alphaev68 ;;
|
||||||
"EV6.8AL (21264B)")
|
"EV6.8AL (21264B)")
|
||||||
UNAME_MACHINE="alphaev68" ;;
|
UNAME_MACHINE=alphaev68 ;;
|
||||||
"EV6.8CX (21264D)")
|
"EV6.8CX (21264D)")
|
||||||
UNAME_MACHINE="alphaev68" ;;
|
UNAME_MACHINE=alphaev68 ;;
|
||||||
"EV6.9A (21264/EV69A)")
|
"EV6.9A (21264/EV69A)")
|
||||||
UNAME_MACHINE="alphaev69" ;;
|
UNAME_MACHINE=alphaev69 ;;
|
||||||
"EV7 (21364)")
|
"EV7 (21364)")
|
||||||
UNAME_MACHINE="alphaev7" ;;
|
UNAME_MACHINE=alphaev7 ;;
|
||||||
"EV7.9 (21364A)")
|
"EV7.9 (21364A)")
|
||||||
UNAME_MACHINE="alphaev79" ;;
|
UNAME_MACHINE=alphaev79 ;;
|
||||||
esac
|
esac
|
||||||
# A Pn.n version is a patched version.
|
# A Pn.n version is a patched version.
|
||||||
# A Vn.n version is a released version.
|
# A Vn.n version is a released version.
|
||||||
# A Tn.n version is a released field test version.
|
# A Tn.n version is a released field test version.
|
||||||
# A Xn.n version is an unreleased experimental baselevel.
|
# A Xn.n version is an unreleased experimental baselevel.
|
||||||
# 1.2 uses "1.2" for uname -r.
|
# 1.2 uses "1.2" for uname -r.
|
||||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
|
||||||
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
|
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
|
||||||
exitcode=$?
|
exitcode=$?
|
||||||
trap '' 0
|
trap '' 0
|
||||||
@@ -359,16 +383,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
exit ;;
|
exit ;;
|
||||||
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
||||||
eval $set_cc_for_build
|
eval $set_cc_for_build
|
||||||
SUN_ARCH="i386"
|
SUN_ARCH=i386
|
||||||
# If there is a compiler, see if it is configured for 64-bit objects.
|
# If there is a compiler, see if it is configured for 64-bit objects.
|
||||||
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
|
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
|
||||||
# This test works for both compilers.
|
# This test works for both compilers.
|
||||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||||
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
|
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||||
grep IS_64BIT_ARCH >/dev/null
|
grep IS_64BIT_ARCH >/dev/null
|
||||||
then
|
then
|
||||||
SUN_ARCH="x86_64"
|
SUN_ARCH=x86_64
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||||
@@ -393,7 +417,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
exit ;;
|
exit ;;
|
||||||
sun*:*:4.2BSD:*)
|
sun*:*:4.2BSD:*)
|
||||||
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
|
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
|
||||||
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
|
test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
|
||||||
case "`/bin/arch`" in
|
case "`/bin/arch`" in
|
||||||
sun3)
|
sun3)
|
||||||
echo m68k-sun-sunos${UNAME_RELEASE}
|
echo m68k-sun-sunos${UNAME_RELEASE}
|
||||||
@@ -579,8 +603,9 @@ EOF
|
|||||||
else
|
else
|
||||||
IBM_ARCH=powerpc
|
IBM_ARCH=powerpc
|
||||||
fi
|
fi
|
||||||
if [ -x /usr/bin/oslevel ] ; then
|
if [ -x /usr/bin/lslpp ] ; then
|
||||||
IBM_REV=`/usr/bin/oslevel`
|
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
|
||||||
|
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
|
||||||
else
|
else
|
||||||
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
|
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
|
||||||
fi
|
fi
|
||||||
@@ -617,13 +642,13 @@ EOF
|
|||||||
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
|
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
|
||||||
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
||||||
case "${sc_cpu_version}" in
|
case "${sc_cpu_version}" in
|
||||||
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
|
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
|
||||||
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
|
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
|
||||||
532) # CPU_PA_RISC2_0
|
532) # CPU_PA_RISC2_0
|
||||||
case "${sc_kernel_bits}" in
|
case "${sc_kernel_bits}" in
|
||||||
32) HP_ARCH="hppa2.0n" ;;
|
32) HP_ARCH=hppa2.0n ;;
|
||||||
64) HP_ARCH="hppa2.0w" ;;
|
64) HP_ARCH=hppa2.0w ;;
|
||||||
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
|
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
|
||||||
esac ;;
|
esac ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
@@ -662,11 +687,11 @@ EOF
|
|||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
(CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
||||||
test -z "$HP_ARCH" && HP_ARCH=hppa
|
test -z "$HP_ARCH" && HP_ARCH=hppa
|
||||||
fi ;;
|
fi ;;
|
||||||
esac
|
esac
|
||||||
if [ ${HP_ARCH} = "hppa2.0w" ]
|
if [ ${HP_ARCH} = hppa2.0w ]
|
||||||
then
|
then
|
||||||
eval $set_cc_for_build
|
eval $set_cc_for_build
|
||||||
|
|
||||||
@@ -679,12 +704,12 @@ EOF
|
|||||||
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
|
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
|
||||||
# => hppa64-hp-hpux11.23
|
# => hppa64-hp-hpux11.23
|
||||||
|
|
||||||
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
|
if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
|
||||||
grep -q __LP64__
|
grep -q __LP64__
|
||||||
then
|
then
|
||||||
HP_ARCH="hppa2.0w"
|
HP_ARCH=hppa2.0w
|
||||||
else
|
else
|
||||||
HP_ARCH="hppa64"
|
HP_ARCH=hppa64
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
|
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
|
||||||
@@ -789,14 +814,14 @@ EOF
|
|||||||
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||||
exit ;;
|
exit ;;
|
||||||
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
||||||
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
|
||||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
|
||||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||||
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||||
exit ;;
|
exit ;;
|
||||||
5000:UNIX_System_V:4.*:*)
|
5000:UNIX_System_V:4.*:*)
|
||||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
|
||||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
|
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
|
||||||
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
||||||
@@ -878,7 +903,7 @@ EOF
|
|||||||
exit ;;
|
exit ;;
|
||||||
*:GNU/*:*:*)
|
*:GNU/*:*:*)
|
||||||
# other systems with GNU libc and userland
|
# other systems with GNU libc and userland
|
||||||
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:Minix:*:*)
|
i*86:Minix:*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-minix
|
echo ${UNAME_MACHINE}-pc-minix
|
||||||
@@ -901,7 +926,7 @@ EOF
|
|||||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||||
esac
|
esac
|
||||||
objdump --private-headers /bin/sh | grep -q ld.so.1
|
objdump --private-headers /bin/sh | grep -q ld.so.1
|
||||||
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
|
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
arc:Linux:*:* | arceb:Linux:*:*)
|
arc:Linux:*:* | arceb:Linux:*:*)
|
||||||
@@ -932,6 +957,9 @@ EOF
|
|||||||
crisv32:Linux:*:*)
|
crisv32:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
|
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
|
e2k:Linux:*:*)
|
||||||
|
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||||
|
exit ;;
|
||||||
frv:Linux:*:*)
|
frv:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -944,6 +972,9 @@ EOF
|
|||||||
ia64:Linux:*:*)
|
ia64:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
|
k1om:Linux:*:*)
|
||||||
|
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||||
|
exit ;;
|
||||||
m32r*:Linux:*:*)
|
m32r*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -969,6 +1000,9 @@ EOF
|
|||||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
|
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
|
||||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
|
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
|
||||||
;;
|
;;
|
||||||
|
mips64el:Linux:*:*)
|
||||||
|
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||||
|
exit ;;
|
||||||
openrisc*:Linux:*:*)
|
openrisc*:Linux:*:*)
|
||||||
echo or1k-unknown-linux-${LIBC}
|
echo or1k-unknown-linux-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -1001,6 +1035,9 @@ EOF
|
|||||||
ppcle:Linux:*:*)
|
ppcle:Linux:*:*)
|
||||||
echo powerpcle-unknown-linux-${LIBC}
|
echo powerpcle-unknown-linux-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
|
riscv32:Linux:*:* | riscv64:Linux:*:*)
|
||||||
|
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||||
|
exit ;;
|
||||||
s390:Linux:*:* | s390x:Linux:*:*)
|
s390:Linux:*:* | s390x:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
|
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -1020,7 +1057,7 @@ EOF
|
|||||||
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
|
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
x86_64:Linux:*:*)
|
x86_64:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
|
||||||
exit ;;
|
exit ;;
|
||||||
xtensa*:Linux:*:*)
|
xtensa*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||||
@@ -1099,7 +1136,7 @@ EOF
|
|||||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||||
# the processor, so we play safe by assuming i586.
|
# the processor, so we play safe by assuming i586.
|
||||||
# Note: whatever this is, it MUST be the same as what config.sub
|
# Note: whatever this is, it MUST be the same as what config.sub
|
||||||
# prints for the "djgpp" host, or else GDB configury will decide that
|
# prints for the "djgpp" host, or else GDB configure will decide that
|
||||||
# this is a cross-build.
|
# this is a cross-build.
|
||||||
echo i586-pc-msdosdjgpp
|
echo i586-pc-msdosdjgpp
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -1248,6 +1285,9 @@ EOF
|
|||||||
SX-8R:SUPER-UX:*:*)
|
SX-8R:SUPER-UX:*:*)
|
||||||
echo sx8r-nec-superux${UNAME_RELEASE}
|
echo sx8r-nec-superux${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
|
SX-ACE:SUPER-UX:*:*)
|
||||||
|
echo sxace-nec-superux${UNAME_RELEASE}
|
||||||
|
exit ;;
|
||||||
Power*:Rhapsody:*:*)
|
Power*:Rhapsody:*:*)
|
||||||
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -1261,9 +1301,9 @@ EOF
|
|||||||
UNAME_PROCESSOR=powerpc
|
UNAME_PROCESSOR=powerpc
|
||||||
fi
|
fi
|
||||||
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
|
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
|
||||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||||
grep IS_64BIT_ARCH >/dev/null
|
grep IS_64BIT_ARCH >/dev/null
|
||||||
then
|
then
|
||||||
case $UNAME_PROCESSOR in
|
case $UNAME_PROCESSOR in
|
||||||
@@ -1285,7 +1325,7 @@ EOF
|
|||||||
exit ;;
|
exit ;;
|
||||||
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
||||||
UNAME_PROCESSOR=`uname -p`
|
UNAME_PROCESSOR=`uname -p`
|
||||||
if test "$UNAME_PROCESSOR" = "x86"; then
|
if test "$UNAME_PROCESSOR" = x86; then
|
||||||
UNAME_PROCESSOR=i386
|
UNAME_PROCESSOR=i386
|
||||||
UNAME_MACHINE=pc
|
UNAME_MACHINE=pc
|
||||||
fi
|
fi
|
||||||
@@ -1316,7 +1356,7 @@ EOF
|
|||||||
# "uname -m" is not consistent, so use $cputype instead. 386
|
# "uname -m" is not consistent, so use $cputype instead. 386
|
||||||
# is converted to i386 for consistency with other x86
|
# is converted to i386 for consistency with other x86
|
||||||
# operating systems.
|
# operating systems.
|
||||||
if test "$cputype" = "386"; then
|
if test "$cputype" = 386; then
|
||||||
UNAME_MACHINE=i386
|
UNAME_MACHINE=i386
|
||||||
else
|
else
|
||||||
UNAME_MACHINE="$cputype"
|
UNAME_MACHINE="$cputype"
|
||||||
@@ -1358,7 +1398,7 @@ EOF
|
|||||||
echo i386-pc-xenix
|
echo i386-pc-xenix
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:skyos:*:*)
|
i*86:skyos:*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
|
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:rdos:*:*)
|
i*86:rdos:*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-rdos
|
echo ${UNAME_MACHINE}-pc-rdos
|
||||||
@@ -1369,23 +1409,25 @@ EOF
|
|||||||
x86_64:VMkernel:*:*)
|
x86_64:VMkernel:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-esx
|
echo ${UNAME_MACHINE}-unknown-esx
|
||||||
exit ;;
|
exit ;;
|
||||||
|
amd64:Isilon\ OneFS:*:*)
|
||||||
|
echo x86_64-unknown-onefs
|
||||||
|
exit ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
cat >&2 <<EOF
|
cat >&2 <<EOF
|
||||||
$0: unable to guess system type
|
$0: unable to guess system type
|
||||||
|
|
||||||
This script, last modified $timestamp, has failed to recognize
|
This script (version $timestamp), has failed to recognize the
|
||||||
the operating system you are using. It is advised that you
|
operating system you are using. If your script is old, overwrite
|
||||||
download the most up to date version of the config scripts from
|
config.guess and config.sub with the latest versions from:
|
||||||
|
|
||||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
|
||||||
and
|
and
|
||||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||||
|
|
||||||
If the version you run ($0) is already up to date, please
|
If $0 has already been updated, send the following data and any
|
||||||
send the following data and any information you think might be
|
information you think might be pertinent to config-patches@gnu.org to
|
||||||
pertinent to <config-patches@gnu.org> in order to provide the needed
|
provide the necessary information to handle your system.
|
||||||
information to handle your system.
|
|
||||||
|
|
||||||
config.guess timestamp = $timestamp
|
config.guess timestamp = $timestamp
|
||||||
|
|
||||||
|
|||||||
76
build-aux/config.sub
vendored
76
build-aux/config.sub
vendored
@@ -1,8 +1,8 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Configuration validation subroutine script.
|
# Configuration validation subroutine script.
|
||||||
# Copyright 1992-2014 Free Software Foundation, Inc.
|
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
timestamp='2014-05-01'
|
timestamp='2016-11-04'
|
||||||
|
|
||||||
# This file is free software; you can redistribute it and/or modify it
|
# This file is free software; you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU General Public License as published by
|
# under the terms of the GNU General Public License as published by
|
||||||
@@ -25,7 +25,7 @@ timestamp='2014-05-01'
|
|||||||
# of the GNU General Public License, version 3 ("GPLv3").
|
# of the GNU General Public License, version 3 ("GPLv3").
|
||||||
|
|
||||||
|
|
||||||
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
|
# Please send patches to <config-patches@gnu.org>.
|
||||||
#
|
#
|
||||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||||
# Supply the specified configuration type as an argument.
|
# Supply the specified configuration type as an argument.
|
||||||
@@ -33,7 +33,7 @@ timestamp='2014-05-01'
|
|||||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||||
|
|
||||||
# You can get the latest version of this script from:
|
# You can get the latest version of this script from:
|
||||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||||
|
|
||||||
# This file is supposed to be the same for all GNU packages
|
# This file is supposed to be the same for all GNU packages
|
||||||
# and recognize all the CPU types, system types and aliases
|
# and recognize all the CPU types, system types and aliases
|
||||||
@@ -53,8 +53,7 @@ timestamp='2014-05-01'
|
|||||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||||
|
|
||||||
usage="\
|
usage="\
|
||||||
Usage: $0 [OPTION] CPU-MFR-OPSYS
|
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
|
||||||
$0 [OPTION] ALIAS
|
|
||||||
|
|
||||||
Canonicalize a configuration name.
|
Canonicalize a configuration name.
|
||||||
|
|
||||||
@@ -68,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
|||||||
version="\
|
version="\
|
||||||
GNU config.sub ($timestamp)
|
GNU config.sub ($timestamp)
|
||||||
|
|
||||||
Copyright 1992-2014 Free Software Foundation, Inc.
|
Copyright 1992-2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This is free software; see the source for copying conditions. There is NO
|
This is free software; see the source for copying conditions. There is NO
|
||||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||||
@@ -117,8 +116,8 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
|||||||
case $maybe_os in
|
case $maybe_os in
|
||||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||||
knetbsd*-gnu* | netbsd*-gnu* | \
|
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
|
||||||
kopensolaris*-gnu* | \
|
kopensolaris*-gnu* | cloudabi*-eabi* | \
|
||||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||||
os=-$maybe_os
|
os=-$maybe_os
|
||||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||||
@@ -255,12 +254,13 @@ case $basic_machine in
|
|||||||
| arc | arceb \
|
| arc | arceb \
|
||||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
||||||
| avr | avr32 \
|
| avr | avr32 \
|
||||||
|
| ba \
|
||||||
| be32 | be64 \
|
| be32 | be64 \
|
||||||
| bfin \
|
| bfin \
|
||||||
| c4x | c8051 | clipper \
|
| c4x | c8051 | clipper \
|
||||||
| d10v | d30v | dlx | dsp16xx \
|
| d10v | d30v | dlx | dsp16xx \
|
||||||
| epiphany \
|
| e2k | epiphany \
|
||||||
| fido | fr30 | frv \
|
| fido | fr30 | frv | ft32 \
|
||||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||||
| hexagon \
|
| hexagon \
|
||||||
| i370 | i860 | i960 | ia64 \
|
| i370 | i860 | i960 | ia64 \
|
||||||
@@ -301,10 +301,12 @@ case $basic_machine in
|
|||||||
| open8 | or1k | or1knd | or32 \
|
| open8 | or1k | or1knd | or32 \
|
||||||
| pdp10 | pdp11 | pj | pjl \
|
| pdp10 | pdp11 | pj | pjl \
|
||||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
||||||
|
| pru \
|
||||||
| pyramid \
|
| pyramid \
|
||||||
|
| riscv32 | riscv64 \
|
||||||
| rl78 | rx \
|
| rl78 | rx \
|
||||||
| score \
|
| score \
|
||||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||||
| sh64 | sh64le \
|
| sh64 | sh64le \
|
||||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||||
@@ -312,6 +314,7 @@ case $basic_machine in
|
|||||||
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
||||||
| ubicom32 \
|
| ubicom32 \
|
||||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
||||||
|
| visium \
|
||||||
| we32k \
|
| we32k \
|
||||||
| x86 | xc16x | xstormy16 | xtensa \
|
| x86 | xc16x | xstormy16 | xtensa \
|
||||||
| z8k | z80)
|
| z8k | z80)
|
||||||
@@ -326,6 +329,9 @@ case $basic_machine in
|
|||||||
c6x)
|
c6x)
|
||||||
basic_machine=tic6x-unknown
|
basic_machine=tic6x-unknown
|
||||||
;;
|
;;
|
||||||
|
leon|leon[3-9])
|
||||||
|
basic_machine=sparc-$basic_machine
|
||||||
|
;;
|
||||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
|
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
|
||||||
basic_machine=$basic_machine-unknown
|
basic_machine=$basic_machine-unknown
|
||||||
os=-none
|
os=-none
|
||||||
@@ -371,12 +377,13 @@ case $basic_machine in
|
|||||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
||||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||||
| avr-* | avr32-* \
|
| avr-* | avr32-* \
|
||||||
|
| ba-* \
|
||||||
| be32-* | be64-* \
|
| be32-* | be64-* \
|
||||||
| bfin-* | bs2000-* \
|
| bfin-* | bs2000-* \
|
||||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||||
| c8051-* | clipper-* | craynv-* | cydra-* \
|
| c8051-* | clipper-* | craynv-* | cydra-* \
|
||||||
| d10v-* | d30v-* | dlx-* \
|
| d10v-* | d30v-* | dlx-* \
|
||||||
| elxsi-* \
|
| e2k-* | elxsi-* \
|
||||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||||
| h8300-* | h8500-* \
|
| h8300-* | h8500-* \
|
||||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||||
@@ -422,13 +429,15 @@ case $basic_machine in
|
|||||||
| orion-* \
|
| orion-* \
|
||||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||||
|
| pru-* \
|
||||||
| pyramid-* \
|
| pyramid-* \
|
||||||
|
| riscv32-* | riscv64-* \
|
||||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
| rl78-* | romp-* | rs6000-* | rx-* \
|
||||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||||
| sparclite-* \
|
| sparclite-* \
|
||||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
|
||||||
| tahoe-* \
|
| tahoe-* \
|
||||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||||
| tile*-* \
|
| tile*-* \
|
||||||
@@ -436,6 +445,7 @@ case $basic_machine in
|
|||||||
| ubicom32-* \
|
| ubicom32-* \
|
||||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
||||||
| vax-* \
|
| vax-* \
|
||||||
|
| visium-* \
|
||||||
| we32k-* \
|
| we32k-* \
|
||||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
||||||
| xstormy16-* | xtensa*-* \
|
| xstormy16-* | xtensa*-* \
|
||||||
@@ -512,6 +522,9 @@ case $basic_machine in
|
|||||||
basic_machine=i386-pc
|
basic_machine=i386-pc
|
||||||
os=-aros
|
os=-aros
|
||||||
;;
|
;;
|
||||||
|
asmjs)
|
||||||
|
basic_machine=asmjs-unknown
|
||||||
|
;;
|
||||||
aux)
|
aux)
|
||||||
basic_machine=m68k-apple
|
basic_machine=m68k-apple
|
||||||
os=-aux
|
os=-aux
|
||||||
@@ -632,6 +645,14 @@ case $basic_machine in
|
|||||||
basic_machine=m68k-bull
|
basic_machine=m68k-bull
|
||||||
os=-sysv3
|
os=-sysv3
|
||||||
;;
|
;;
|
||||||
|
e500v[12])
|
||||||
|
basic_machine=powerpc-unknown
|
||||||
|
os=$os"spe"
|
||||||
|
;;
|
||||||
|
e500v[12]-*)
|
||||||
|
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
os=$os"spe"
|
||||||
|
;;
|
||||||
ebmon29k)
|
ebmon29k)
|
||||||
basic_machine=a29k-amd
|
basic_machine=a29k-amd
|
||||||
os=-ebmon
|
os=-ebmon
|
||||||
@@ -773,6 +794,9 @@ case $basic_machine in
|
|||||||
basic_machine=m68k-isi
|
basic_machine=m68k-isi
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
|
leon-*|leon[3-9]-*)
|
||||||
|
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
|
||||||
|
;;
|
||||||
m68knommu)
|
m68knommu)
|
||||||
basic_machine=m68k-unknown
|
basic_machine=m68k-unknown
|
||||||
os=-linux
|
os=-linux
|
||||||
@@ -828,6 +852,10 @@ case $basic_machine in
|
|||||||
basic_machine=powerpc-unknown
|
basic_machine=powerpc-unknown
|
||||||
os=-morphos
|
os=-morphos
|
||||||
;;
|
;;
|
||||||
|
moxiebox)
|
||||||
|
basic_machine=moxie-unknown
|
||||||
|
os=-moxiebox
|
||||||
|
;;
|
||||||
msdos)
|
msdos)
|
||||||
basic_machine=i386-pc
|
basic_machine=i386-pc
|
||||||
os=-msdos
|
os=-msdos
|
||||||
@@ -1004,7 +1032,7 @@ case $basic_machine in
|
|||||||
ppc-* | ppcbe-*)
|
ppc-* | ppcbe-*)
|
||||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
ppcle | powerpclittle)
|
||||||
basic_machine=powerpcle-unknown
|
basic_machine=powerpcle-unknown
|
||||||
;;
|
;;
|
||||||
ppcle-* | powerpclittle-*)
|
ppcle-* | powerpclittle-*)
|
||||||
@@ -1014,7 +1042,7 @@ case $basic_machine in
|
|||||||
;;
|
;;
|
||||||
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
|
ppc64le | powerpc64little)
|
||||||
basic_machine=powerpc64le-unknown
|
basic_machine=powerpc64le-unknown
|
||||||
;;
|
;;
|
||||||
ppc64le-* | powerpc64little-*)
|
ppc64le-* | powerpc64little-*)
|
||||||
@@ -1360,27 +1388,28 @@ case $os in
|
|||||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||||
| -sym* | -kopensolaris* | -plan9* \
|
| -sym* | -kopensolaris* | -plan9* \
|
||||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||||
| -aos* | -aros* \
|
| -aos* | -aros* | -cloudabi* | -sortix* \
|
||||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||||
| -bitrig* | -openbsd* | -solidbsd* \
|
| -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
|
||||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||||
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
| -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
||||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
|
||||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
|
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
|
||||||
|
| -onefs* | -tirtos* | -phoenix* | -fuchsia*)
|
||||||
# Remember, each alternative MUST END IN *, to match a version number.
|
# Remember, each alternative MUST END IN *, to match a version number.
|
||||||
;;
|
;;
|
||||||
-qnx*)
|
-qnx*)
|
||||||
@@ -1404,9 +1433,6 @@ case $os in
|
|||||||
-mac*)
|
-mac*)
|
||||||
os=`echo $os | sed -e 's|mac|macos|'`
|
os=`echo $os | sed -e 's|mac|macos|'`
|
||||||
;;
|
;;
|
||||||
# Apple iOS
|
|
||||||
-ios*)
|
|
||||||
;;
|
|
||||||
-linux-dietlibc)
|
-linux-dietlibc)
|
||||||
os=-linux-dietlibc
|
os=-linux-dietlibc
|
||||||
;;
|
;;
|
||||||
@@ -1515,6 +1541,8 @@ case $os in
|
|||||||
;;
|
;;
|
||||||
-nacl*)
|
-nacl*)
|
||||||
;;
|
;;
|
||||||
|
-ios)
|
||||||
|
;;
|
||||||
-none)
|
-none)
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|||||||
306
configure.ac
306
configure.ac
@@ -118,6 +118,7 @@ dnl If CFLAGS isn't defined, set CFLAGS to something reasonable. Otherwise,
|
|||||||
dnl just prevent autoconf from molesting CFLAGS.
|
dnl just prevent autoconf from molesting CFLAGS.
|
||||||
CFLAGS=$CFLAGS
|
CFLAGS=$CFLAGS
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
|
||||||
if test "x$GCC" != "xyes" ; then
|
if test "x$GCC" != "xyes" ; then
|
||||||
AC_CACHE_CHECK([whether compiler is MSVC],
|
AC_CACHE_CHECK([whether compiler is MSVC],
|
||||||
[je_cv_msvc],
|
[je_cv_msvc],
|
||||||
@@ -131,12 +132,53 @@ if test "x$GCC" != "xyes" ; then
|
|||||||
[je_cv_msvc=no])])
|
[je_cv_msvc=no])])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dnl check if a cray prgenv wrapper compiler is being used
|
||||||
|
je_cv_cray_prgenv_wrapper=""
|
||||||
|
if test "x${PE_ENV}" != "x" ; then
|
||||||
|
case "${CC}" in
|
||||||
|
CC|cc)
|
||||||
|
je_cv_cray_prgenv_wrapper="yes"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([whether compiler is cray],
|
||||||
|
[je_cv_cray],
|
||||||
|
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
|
||||||
|
[
|
||||||
|
#ifndef _CRAYC
|
||||||
|
int fail[-1];
|
||||||
|
#endif
|
||||||
|
])],
|
||||||
|
[je_cv_cray=yes],
|
||||||
|
[je_cv_cray=no])])
|
||||||
|
|
||||||
|
if test "x${je_cv_cray}" = "xyes" ; then
|
||||||
|
AC_CACHE_CHECK([whether cray compiler version is 8.4],
|
||||||
|
[je_cv_cray_84],
|
||||||
|
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
|
||||||
|
[
|
||||||
|
#if !(_RELEASE_MAJOR == 8 && _RELEASE_MINOR == 4)
|
||||||
|
int fail[-1];
|
||||||
|
#endif
|
||||||
|
])],
|
||||||
|
[je_cv_cray_84=yes],
|
||||||
|
[je_cv_cray_84=no])])
|
||||||
|
fi
|
||||||
|
|
||||||
if test "x$CFLAGS" = "x" ; then
|
if test "x$CFLAGS" = "x" ; then
|
||||||
no_CFLAGS="yes"
|
no_CFLAGS="yes"
|
||||||
if test "x$GCC" = "xyes" ; then
|
if test "x$GCC" = "xyes" ; then
|
||||||
JE_CFLAGS_APPEND([-std=gnu99])
|
JE_CFLAGS_APPEND([-std=gnu11])
|
||||||
if test "x$je_cv_cflags_appended" = "x-std=gnu99" ; then
|
if test "x$je_cv_cflags_appended" = "x-std=gnu11" ; then
|
||||||
AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT])
|
AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT])
|
||||||
|
else
|
||||||
|
JE_CFLAGS_APPEND([-std=gnu99])
|
||||||
|
if test "x$je_cv_cflags_appended" = "x-std=gnu99" ; then
|
||||||
|
AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT])
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
JE_CFLAGS_APPEND([-Wall])
|
JE_CFLAGS_APPEND([-Wall])
|
||||||
JE_CFLAGS_APPEND([-Werror=declaration-after-statement])
|
JE_CFLAGS_APPEND([-Werror=declaration-after-statement])
|
||||||
@@ -152,11 +194,21 @@ if test "x$CFLAGS" = "x" ; then
|
|||||||
JE_CFLAGS_APPEND([-FS])
|
JE_CFLAGS_APPEND([-FS])
|
||||||
CPPFLAGS="$CPPFLAGS -I${srcdir}/include/msvc_compat"
|
CPPFLAGS="$CPPFLAGS -I${srcdir}/include/msvc_compat"
|
||||||
fi
|
fi
|
||||||
|
if test "x$je_cv_cray" = "xyes" ; then
|
||||||
|
dnl cray compiler 8.4 has an inlining bug
|
||||||
|
if test "x$je_cv_cray_84" = "xyes" ; then
|
||||||
|
JE_CFLAGS_APPEND([-hipa2])
|
||||||
|
JE_CFLAGS_APPEND([-hnognu])
|
||||||
|
fi
|
||||||
|
if test "x$enable_cc_silence" != "xno" ; then
|
||||||
|
dnl ignore unreachable code warning
|
||||||
|
JE_CFLAGS_APPEND([-hnomessage=128])
|
||||||
|
dnl ignore redefinition of "malloc", "free", etc warning
|
||||||
|
JE_CFLAGS_APPEND([-hnomessage=1357])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
dnl Append EXTRA_CFLAGS to CFLAGS, if defined.
|
AC_SUBST([EXTRA_CFLAGS])
|
||||||
if test "x$EXTRA_CFLAGS" != "x" ; then
|
|
||||||
JE_CFLAGS_APPEND([$EXTRA_CFLAGS])
|
|
||||||
fi
|
|
||||||
AC_PROG_CPP
|
AC_PROG_CPP
|
||||||
|
|
||||||
AC_C_BIGENDIAN([ac_cv_big_endian=1], [ac_cv_big_endian=0])
|
AC_C_BIGENDIAN([ac_cv_big_endian=1], [ac_cv_big_endian=0])
|
||||||
@@ -263,17 +315,27 @@ o="$ac_objext"
|
|||||||
a="a"
|
a="a"
|
||||||
exe="$ac_exeext"
|
exe="$ac_exeext"
|
||||||
libprefix="lib"
|
libprefix="lib"
|
||||||
|
link_whole_archive="0"
|
||||||
DSO_LDFLAGS='-shared -Wl,-soname,$(@F)'
|
DSO_LDFLAGS='-shared -Wl,-soname,$(@F)'
|
||||||
RPATH='-Wl,-rpath,$(1)'
|
RPATH='-Wl,-rpath,$(1)'
|
||||||
SOREV="${so}.${rev}"
|
SOREV="${so}.${rev}"
|
||||||
PIC_CFLAGS='-fPIC -DPIC'
|
PIC_CFLAGS='-fPIC -DPIC'
|
||||||
CTARGET='-o $@'
|
CTARGET='-o $@'
|
||||||
LDTARGET='-o $@'
|
LDTARGET='-o $@'
|
||||||
|
TEST_LD_MODE=
|
||||||
EXTRA_LDFLAGS=
|
EXTRA_LDFLAGS=
|
||||||
ARFLAGS='crus'
|
ARFLAGS='crus'
|
||||||
AROUT=' $@'
|
AROUT=' $@'
|
||||||
CC_MM=1
|
CC_MM=1
|
||||||
|
|
||||||
|
if test "x$je_cv_cray_prgenv_wrapper" = "xyes" ; then
|
||||||
|
TEST_LD_MODE='-dynamic'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x${je_cv_cray}" = "xyes" ; then
|
||||||
|
CC_MM=
|
||||||
|
fi
|
||||||
|
|
||||||
AN_MAKEVAR([AR], [AC_PROG_AR])
|
AN_MAKEVAR([AR], [AC_PROG_AR])
|
||||||
AN_PROGRAM([ar], [AC_PROG_AR])
|
AN_PROGRAM([ar], [AC_PROG_AR])
|
||||||
AC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)])
|
AC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)])
|
||||||
@@ -286,13 +348,12 @@ dnl
|
|||||||
dnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the
|
dnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the
|
||||||
dnl definitions need to be seen before any headers are included, which is a pain
|
dnl definitions need to be seen before any headers are included, which is a pain
|
||||||
dnl to make happen otherwise.
|
dnl to make happen otherwise.
|
||||||
|
CFLAGS="$CFLAGS"
|
||||||
default_munmap="1"
|
default_munmap="1"
|
||||||
maps_coalesce="1"
|
maps_coalesce="1"
|
||||||
case "${host}" in
|
case "${host}" in
|
||||||
*-*-darwin* | *-*-ios*)
|
*-*-darwin* | *-*-ios*)
|
||||||
CFLAGS="$CFLAGS"
|
|
||||||
abi="macho"
|
abi="macho"
|
||||||
AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
|
|
||||||
RPATH=""
|
RPATH=""
|
||||||
LD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
|
LD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
|
||||||
so="dylib"
|
so="dylib"
|
||||||
@@ -303,35 +364,37 @@ case "${host}" in
|
|||||||
sbrk_deprecated="1"
|
sbrk_deprecated="1"
|
||||||
;;
|
;;
|
||||||
*-*-freebsd*)
|
*-*-freebsd*)
|
||||||
CFLAGS="$CFLAGS"
|
|
||||||
abi="elf"
|
abi="elf"
|
||||||
AC_DEFINE([JEMALLOC_SYSCTL_VM_OVERCOMMIT], [ ])
|
AC_DEFINE([JEMALLOC_SYSCTL_VM_OVERCOMMIT], [ ])
|
||||||
AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
|
|
||||||
force_lazy_lock="1"
|
force_lazy_lock="1"
|
||||||
;;
|
;;
|
||||||
*-*-dragonfly*)
|
*-*-dragonfly*)
|
||||||
CFLAGS="$CFLAGS"
|
|
||||||
abi="elf"
|
abi="elf"
|
||||||
AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
|
|
||||||
;;
|
;;
|
||||||
*-*-openbsd*)
|
*-*-openbsd*)
|
||||||
CFLAGS="$CFLAGS"
|
|
||||||
abi="elf"
|
abi="elf"
|
||||||
AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
|
|
||||||
force_tls="0"
|
force_tls="0"
|
||||||
;;
|
;;
|
||||||
*-*-bitrig*)
|
*-*-bitrig*)
|
||||||
CFLAGS="$CFLAGS"
|
|
||||||
abi="elf"
|
abi="elf"
|
||||||
AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
|
|
||||||
;;
|
;;
|
||||||
*-*-linux*)
|
*-*-linux-android)
|
||||||
CFLAGS="$CFLAGS"
|
dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE.
|
||||||
|
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
|
||||||
|
abi="elf"
|
||||||
|
AC_DEFINE([JEMALLOC_HAS_ALLOCA_H])
|
||||||
|
AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ])
|
||||||
|
AC_DEFINE([JEMALLOC_THREADED_INIT], [ ])
|
||||||
|
AC_DEFINE([JEMALLOC_C11ATOMICS])
|
||||||
|
force_tls="0"
|
||||||
|
default_munmap="0"
|
||||||
|
;;
|
||||||
|
*-*-linux* | *-*-kfreebsd*)
|
||||||
|
dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE.
|
||||||
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
|
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
|
||||||
abi="elf"
|
abi="elf"
|
||||||
AC_DEFINE([JEMALLOC_HAS_ALLOCA_H])
|
AC_DEFINE([JEMALLOC_HAS_ALLOCA_H])
|
||||||
AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ])
|
AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ])
|
||||||
AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED], [ ])
|
|
||||||
AC_DEFINE([JEMALLOC_THREADED_INIT], [ ])
|
AC_DEFINE([JEMALLOC_THREADED_INIT], [ ])
|
||||||
AC_DEFINE([JEMALLOC_USE_CXX_THROW], [ ])
|
AC_DEFINE([JEMALLOC_USE_CXX_THROW], [ ])
|
||||||
default_munmap="0"
|
default_munmap="0"
|
||||||
@@ -345,15 +408,12 @@ case "${host}" in
|
|||||||
#error aout
|
#error aout
|
||||||
#endif
|
#endif
|
||||||
]])],
|
]])],
|
||||||
[CFLAGS="$CFLAGS"; abi="elf"],
|
[abi="elf"],
|
||||||
[abi="aout"])
|
[abi="aout"])
|
||||||
AC_MSG_RESULT([$abi])
|
AC_MSG_RESULT([$abi])
|
||||||
AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
|
|
||||||
;;
|
;;
|
||||||
*-*-solaris2*)
|
*-*-solaris2*)
|
||||||
CFLAGS="$CFLAGS"
|
|
||||||
abi="elf"
|
abi="elf"
|
||||||
AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
|
|
||||||
RPATH='-Wl,-R,$(1)'
|
RPATH='-Wl,-R,$(1)'
|
||||||
dnl Solaris needs this for sigwait().
|
dnl Solaris needs this for sigwait().
|
||||||
CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS"
|
CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS"
|
||||||
@@ -372,7 +432,6 @@ case "${host}" in
|
|||||||
*-*-mingw* | *-*-cygwin*)
|
*-*-mingw* | *-*-cygwin*)
|
||||||
abi="pecoff"
|
abi="pecoff"
|
||||||
force_tls="0"
|
force_tls="0"
|
||||||
force_lazy_lock="1"
|
|
||||||
maps_coalesce="0"
|
maps_coalesce="0"
|
||||||
RPATH=""
|
RPATH=""
|
||||||
so="dll"
|
so="dll"
|
||||||
@@ -389,6 +448,7 @@ case "${host}" in
|
|||||||
else
|
else
|
||||||
importlib="${so}"
|
importlib="${so}"
|
||||||
DSO_LDFLAGS="-shared"
|
DSO_LDFLAGS="-shared"
|
||||||
|
link_whole_archive="1"
|
||||||
fi
|
fi
|
||||||
a="lib"
|
a="lib"
|
||||||
libprefix=""
|
libprefix=""
|
||||||
@@ -426,17 +486,28 @@ AC_SUBST([o])
|
|||||||
AC_SUBST([a])
|
AC_SUBST([a])
|
||||||
AC_SUBST([exe])
|
AC_SUBST([exe])
|
||||||
AC_SUBST([libprefix])
|
AC_SUBST([libprefix])
|
||||||
|
AC_SUBST([link_whole_archive])
|
||||||
AC_SUBST([DSO_LDFLAGS])
|
AC_SUBST([DSO_LDFLAGS])
|
||||||
AC_SUBST([EXTRA_LDFLAGS])
|
AC_SUBST([EXTRA_LDFLAGS])
|
||||||
AC_SUBST([SOREV])
|
AC_SUBST([SOREV])
|
||||||
AC_SUBST([PIC_CFLAGS])
|
AC_SUBST([PIC_CFLAGS])
|
||||||
AC_SUBST([CTARGET])
|
AC_SUBST([CTARGET])
|
||||||
AC_SUBST([LDTARGET])
|
AC_SUBST([LDTARGET])
|
||||||
|
AC_SUBST([TEST_LD_MODE])
|
||||||
AC_SUBST([MKLIB])
|
AC_SUBST([MKLIB])
|
||||||
AC_SUBST([ARFLAGS])
|
AC_SUBST([ARFLAGS])
|
||||||
AC_SUBST([AROUT])
|
AC_SUBST([AROUT])
|
||||||
AC_SUBST([CC_MM])
|
AC_SUBST([CC_MM])
|
||||||
|
|
||||||
|
dnl Determine whether libm must be linked to use e.g. log(3).
|
||||||
|
AC_SEARCH_LIBS([log], [m], , [AC_MSG_ERROR([Missing math functions])])
|
||||||
|
if test "x$ac_cv_search_log" != "xnone required" ; then
|
||||||
|
LM="$ac_cv_search_log"
|
||||||
|
else
|
||||||
|
LM=
|
||||||
|
fi
|
||||||
|
AC_SUBST(LM)
|
||||||
|
|
||||||
JE_COMPILABLE([__attribute__ syntax],
|
JE_COMPILABLE([__attribute__ syntax],
|
||||||
[static __attribute__((unused)) void foo(void){}],
|
[static __attribute__((unused)) void foo(void){}],
|
||||||
[],
|
[],
|
||||||
@@ -450,6 +521,7 @@ fi
|
|||||||
dnl Check for tls_model attribute support (clang 3.0 still lacks support).
|
dnl Check for tls_model attribute support (clang 3.0 still lacks support).
|
||||||
SAVED_CFLAGS="${CFLAGS}"
|
SAVED_CFLAGS="${CFLAGS}"
|
||||||
JE_CFLAGS_APPEND([-Werror])
|
JE_CFLAGS_APPEND([-Werror])
|
||||||
|
JE_CFLAGS_APPEND([-herror_on_warning])
|
||||||
JE_COMPILABLE([tls_model attribute], [],
|
JE_COMPILABLE([tls_model attribute], [],
|
||||||
[static __thread int
|
[static __thread int
|
||||||
__attribute__((tls_model("initial-exec"), unused)) foo;
|
__attribute__((tls_model("initial-exec"), unused)) foo;
|
||||||
@@ -465,6 +537,7 @@ fi
|
|||||||
dnl Check for alloc_size attribute support.
|
dnl Check for alloc_size attribute support.
|
||||||
SAVED_CFLAGS="${CFLAGS}"
|
SAVED_CFLAGS="${CFLAGS}"
|
||||||
JE_CFLAGS_APPEND([-Werror])
|
JE_CFLAGS_APPEND([-Werror])
|
||||||
|
JE_CFLAGS_APPEND([-herror_on_warning])
|
||||||
JE_COMPILABLE([alloc_size attribute], [#include <stdlib.h>],
|
JE_COMPILABLE([alloc_size attribute], [#include <stdlib.h>],
|
||||||
[void *foo(size_t size) __attribute__((alloc_size(1)));],
|
[void *foo(size_t size) __attribute__((alloc_size(1)));],
|
||||||
[je_cv_alloc_size])
|
[je_cv_alloc_size])
|
||||||
@@ -475,6 +548,7 @@ fi
|
|||||||
dnl Check for format(gnu_printf, ...) attribute support.
|
dnl Check for format(gnu_printf, ...) attribute support.
|
||||||
SAVED_CFLAGS="${CFLAGS}"
|
SAVED_CFLAGS="${CFLAGS}"
|
||||||
JE_CFLAGS_APPEND([-Werror])
|
JE_CFLAGS_APPEND([-Werror])
|
||||||
|
JE_CFLAGS_APPEND([-herror_on_warning])
|
||||||
JE_COMPILABLE([format(gnu_printf, ...) attribute], [#include <stdlib.h>],
|
JE_COMPILABLE([format(gnu_printf, ...) attribute], [#include <stdlib.h>],
|
||||||
[void *foo(const char *format, ...) __attribute__((format(gnu_printf, 1, 2)));],
|
[void *foo(const char *format, ...) __attribute__((format(gnu_printf, 1, 2)));],
|
||||||
[je_cv_format_gnu_printf])
|
[je_cv_format_gnu_printf])
|
||||||
@@ -485,6 +559,7 @@ fi
|
|||||||
dnl Check for format(printf, ...) attribute support.
|
dnl Check for format(printf, ...) attribute support.
|
||||||
SAVED_CFLAGS="${CFLAGS}"
|
SAVED_CFLAGS="${CFLAGS}"
|
||||||
JE_CFLAGS_APPEND([-Werror])
|
JE_CFLAGS_APPEND([-Werror])
|
||||||
|
JE_CFLAGS_APPEND([-herror_on_warning])
|
||||||
JE_COMPILABLE([format(printf, ...) attribute], [#include <stdlib.h>],
|
JE_COMPILABLE([format(printf, ...) attribute], [#include <stdlib.h>],
|
||||||
[void *foo(const char *format, ...) __attribute__((format(printf, 1, 2)));],
|
[void *foo(const char *format, ...) __attribute__((format(printf, 1, 2)));],
|
||||||
[je_cv_format_printf])
|
[je_cv_format_printf])
|
||||||
@@ -879,9 +954,9 @@ fi
|
|||||||
AC_MSG_CHECKING([configured backtracing method])
|
AC_MSG_CHECKING([configured backtracing method])
|
||||||
AC_MSG_RESULT([$backtrace_method])
|
AC_MSG_RESULT([$backtrace_method])
|
||||||
if test "x$enable_prof" = "x1" ; then
|
if test "x$enable_prof" = "x1" ; then
|
||||||
if test "x$abi" != "xpecoff"; then
|
dnl Heap profiling uses the log(3) function.
|
||||||
dnl Heap profiling uses the log(3) function.
|
if test "x$LM" != "x" ; then
|
||||||
LIBS="$LIBS -lm"
|
LIBS="$LIBS $LM"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_DEFINE([JEMALLOC_PROF], [ ])
|
AC_DEFINE([JEMALLOC_PROF], [ ])
|
||||||
@@ -1050,6 +1125,23 @@ if test "x$enable_cache_oblivious" = "x1" ; then
|
|||||||
fi
|
fi
|
||||||
AC_SUBST([enable_cache_oblivious])
|
AC_SUBST([enable_cache_oblivious])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
JE_COMPILABLE([a program using __builtin_unreachable], [
|
||||||
|
void foo (void) {
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
], [
|
||||||
|
{
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
], [je_cv_gcc_builtin_unreachable])
|
||||||
|
if test "x${je_cv_gcc_builtin_unreachable}" = "xyes" ; then
|
||||||
|
AC_DEFINE([JEMALLOC_INTERNAL_UNREACHABLE], [__builtin_unreachable])
|
||||||
|
else
|
||||||
|
AC_DEFINE([JEMALLOC_INTERNAL_UNREACHABLE], [abort])
|
||||||
|
fi
|
||||||
|
|
||||||
dnl ============================================================================
|
dnl ============================================================================
|
||||||
dnl Check for __builtin_ffsl(), then ffsl(3), and fail if neither are found.
|
dnl Check for __builtin_ffsl(), then ffsl(3), and fail if neither are found.
|
||||||
dnl One of those two functions should (theoretically) exist on all platforms
|
dnl One of those two functions should (theoretically) exist on all platforms
|
||||||
@@ -1237,6 +1329,14 @@ if test "x$abi" != "xpecoff" ; then
|
|||||||
AC_CHECK_LIB([pthread], [pthread_create], [LIBS="$LIBS -lpthread"],
|
AC_CHECK_LIB([pthread], [pthread_create], [LIBS="$LIBS -lpthread"],
|
||||||
[AC_SEARCH_LIBS([pthread_create], , ,
|
[AC_SEARCH_LIBS([pthread_create], , ,
|
||||||
AC_MSG_ERROR([libpthread is missing]))])
|
AC_MSG_ERROR([libpthread is missing]))])
|
||||||
|
JE_COMPILABLE([pthread_atfork(3)], [
|
||||||
|
#include <pthread.h>
|
||||||
|
], [
|
||||||
|
pthread_atfork((void *)0, (void *)0, (void *)0);
|
||||||
|
], [je_cv_pthread_atfork])
|
||||||
|
if test "x${je_cv_pthread_atfork}" = "xyes" ; then
|
||||||
|
AC_DEFINE([JEMALLOC_HAVE_PTHREAD_ATFORK], [ ])
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS -D_REENTRANT"
|
CPPFLAGS="$CPPFLAGS -D_REENTRANT"
|
||||||
@@ -1244,6 +1344,87 @@ CPPFLAGS="$CPPFLAGS -D_REENTRANT"
|
|||||||
dnl Check whether clock_gettime(2) is in libc or librt.
|
dnl Check whether clock_gettime(2) is in libc or librt.
|
||||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||||
|
|
||||||
|
dnl Cray wrapper compiler often adds `-lrt` when using `-static`. Check with
|
||||||
|
dnl `-dynamic` as well in case a user tries to dynamically link in jemalloc
|
||||||
|
if test "x$je_cv_cray_prgenv_wrapper" = "xyes" ; then
|
||||||
|
if test "$ac_cv_search_clock_gettime" != "-lrt"; then
|
||||||
|
SAVED_CFLAGS="${CFLAGS}"
|
||||||
|
|
||||||
|
unset ac_cv_search_clock_gettime
|
||||||
|
JE_CFLAGS_APPEND([-dynamic])
|
||||||
|
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||||
|
|
||||||
|
CFLAGS="${SAVED_CFLAGS}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl check for CLOCK_MONOTONIC_COARSE (Linux-specific).
|
||||||
|
JE_COMPILABLE([clock_gettime(CLOCK_MONOTONIC_COARSE, ...)], [
|
||||||
|
#include <time.h>
|
||||||
|
], [
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
|
||||||
|
], [je_cv_clock_monotonic_coarse])
|
||||||
|
if test "x${je_cv_clock_monotonic_coarse}" = "xyes" ; then
|
||||||
|
AC_DEFINE([JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl check for CLOCK_MONOTONIC.
|
||||||
|
JE_COMPILABLE([clock_gettime(CLOCK_MONOTONIC, ...)], [
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
], [
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
#if !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0
|
||||||
|
# error _POSIX_MONOTONIC_CLOCK missing/invalid
|
||||||
|
#endif
|
||||||
|
], [je_cv_clock_monotonic])
|
||||||
|
if test "x${je_cv_clock_monotonic}" = "xyes" ; then
|
||||||
|
AC_DEFINE([JEMALLOC_HAVE_CLOCK_MONOTONIC])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Check for mach_absolute_time().
|
||||||
|
JE_COMPILABLE([mach_absolute_time()], [
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
], [
|
||||||
|
mach_absolute_time();
|
||||||
|
], [je_cv_mach_absolute_time])
|
||||||
|
if test "x${je_cv_mach_absolute_time}" = "xyes" ; then
|
||||||
|
AC_DEFINE([JEMALLOC_HAVE_MACH_ABSOLUTE_TIME])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Use syscall(2) (if available) by default.
|
||||||
|
AC_ARG_ENABLE([syscall],
|
||||||
|
[AS_HELP_STRING([--disable-syscall], [Disable use of syscall(2)])],
|
||||||
|
[if test "x$enable_syscall" = "xno" ; then
|
||||||
|
enable_syscall="0"
|
||||||
|
else
|
||||||
|
enable_syscall="1"
|
||||||
|
fi
|
||||||
|
],
|
||||||
|
[enable_syscall="1"]
|
||||||
|
)
|
||||||
|
if test "x$enable_syscall" = "x1" ; then
|
||||||
|
dnl Check if syscall(2) is usable. Treat warnings as errors, so that e.g. OS
|
||||||
|
dnl X 10.12's deprecation warning prevents use.
|
||||||
|
SAVED_CFLAGS="${CFLAGS}"
|
||||||
|
JE_CFLAGS_APPEND([-Werror])
|
||||||
|
JE_COMPILABLE([syscall(2)], [
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
], [
|
||||||
|
syscall(SYS_write, 2, "hello", 5);
|
||||||
|
],
|
||||||
|
[je_cv_syscall])
|
||||||
|
CFLAGS="${SAVED_CFLAGS}"
|
||||||
|
if test "x$je_cv_syscall" = "xyes" ; then
|
||||||
|
AC_DEFINE([JEMALLOC_USE_SYSCALL], [ ])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
dnl Check if the GNU-specific secure_getenv function exists.
|
dnl Check if the GNU-specific secure_getenv function exists.
|
||||||
AC_CHECK_FUNC([secure_getenv],
|
AC_CHECK_FUNC([secure_getenv],
|
||||||
[have_secure_getenv="1"],
|
[have_secure_getenv="1"],
|
||||||
@@ -1298,9 +1479,17 @@ fi
|
|||||||
],
|
],
|
||||||
[enable_lazy_lock=""]
|
[enable_lazy_lock=""]
|
||||||
)
|
)
|
||||||
if test "x$enable_lazy_lock" = "x" -a "x${force_lazy_lock}" = "x1" ; then
|
if test "x${enable_lazy_lock}" = "x" ; then
|
||||||
AC_MSG_RESULT([Forcing lazy-lock to avoid allocator/threading bootstrap issues])
|
if test "x${force_lazy_lock}" = "x1" ; then
|
||||||
enable_lazy_lock="1"
|
AC_MSG_RESULT([Forcing lazy-lock to avoid allocator/threading bootstrap issues])
|
||||||
|
enable_lazy_lock="1"
|
||||||
|
else
|
||||||
|
enable_lazy_lock="0"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "x${enable_lazy_lock}" = "x1" -a "x${abi}" = "xpecoff" ; then
|
||||||
|
AC_MSG_RESULT([Forcing no lazy-lock because thread creation monitoring is unimplemented])
|
||||||
|
enable_lazy_lock="0"
|
||||||
fi
|
fi
|
||||||
if test "x$enable_lazy_lock" = "x1" ; then
|
if test "x$enable_lazy_lock" = "x1" ; then
|
||||||
if test "x$abi" != "xpecoff" ; then
|
if test "x$abi" != "xpecoff" ; then
|
||||||
@@ -1311,8 +1500,6 @@ if test "x$enable_lazy_lock" = "x1" ; then
|
|||||||
])
|
])
|
||||||
fi
|
fi
|
||||||
AC_DEFINE([JEMALLOC_LAZY_LOCK], [ ])
|
AC_DEFINE([JEMALLOC_LAZY_LOCK], [ ])
|
||||||
else
|
|
||||||
enable_lazy_lock="0"
|
|
||||||
fi
|
fi
|
||||||
AC_SUBST([enable_lazy_lock])
|
AC_SUBST([enable_lazy_lock])
|
||||||
|
|
||||||
@@ -1435,12 +1622,41 @@ dnl Check for madvise(2).
|
|||||||
JE_COMPILABLE([madvise(2)], [
|
JE_COMPILABLE([madvise(2)], [
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
], [
|
], [
|
||||||
{
|
madvise((void *)0, 0, 0);
|
||||||
madvise((void *)0, 0, 0);
|
|
||||||
}
|
|
||||||
], [je_cv_madvise])
|
], [je_cv_madvise])
|
||||||
if test "x${je_cv_madvise}" = "xyes" ; then
|
if test "x${je_cv_madvise}" = "xyes" ; then
|
||||||
AC_DEFINE([JEMALLOC_HAVE_MADVISE], [ ])
|
AC_DEFINE([JEMALLOC_HAVE_MADVISE], [ ])
|
||||||
|
|
||||||
|
dnl Check for madvise(..., MADV_FREE).
|
||||||
|
JE_COMPILABLE([madvise(..., MADV_FREE)], [
|
||||||
|
#include <sys/mman.h>
|
||||||
|
], [
|
||||||
|
madvise((void *)0, 0, MADV_FREE);
|
||||||
|
], [je_cv_madv_free])
|
||||||
|
if test "x${je_cv_madv_free}" = "xyes" ; then
|
||||||
|
AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Check for madvise(..., MADV_DONTNEED).
|
||||||
|
JE_COMPILABLE([madvise(..., MADV_DONTNEED)], [
|
||||||
|
#include <sys/mman.h>
|
||||||
|
], [
|
||||||
|
madvise((void *)0, 0, MADV_DONTNEED);
|
||||||
|
], [je_cv_madv_dontneed])
|
||||||
|
if test "x${je_cv_madv_dontneed}" = "xyes" ; then
|
||||||
|
AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED], [ ])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Check for madvise(..., MADV_[NO]HUGEPAGE).
|
||||||
|
JE_COMPILABLE([madvise(..., MADV_[[NO]]HUGEPAGE)], [
|
||||||
|
#include <sys/mman.h>
|
||||||
|
], [
|
||||||
|
madvise((void *)0, 0, MADV_HUGEPAGE);
|
||||||
|
madvise((void *)0, 0, MADV_NOHUGEPAGE);
|
||||||
|
], [je_cv_thp])
|
||||||
|
if test "x${je_cv_thp}" = "xyes" ; then
|
||||||
|
AC_DEFINE([JEMALLOC_THP], [ ])
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl ============================================================================
|
dnl ============================================================================
|
||||||
@@ -1500,6 +1716,25 @@ if test "x${je_cv_builtin_clz}" = "xyes" ; then
|
|||||||
AC_DEFINE([JEMALLOC_HAVE_BUILTIN_CLZ], [ ])
|
AC_DEFINE([JEMALLOC_HAVE_BUILTIN_CLZ], [ ])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dnl ============================================================================
|
||||||
|
dnl Check for os_unfair_lock operations as provided on Darwin.
|
||||||
|
|
||||||
|
JE_COMPILABLE([Darwin os_unfair_lock_*()], [
|
||||||
|
#include <os/lock.h>
|
||||||
|
#include <AvailabilityMacros.h>
|
||||||
|
], [
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101200
|
||||||
|
#error "os_unfair_lock is not supported"
|
||||||
|
#else
|
||||||
|
os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
|
||||||
|
os_unfair_lock_lock(&lock);
|
||||||
|
os_unfair_lock_unlock(&lock);
|
||||||
|
#endif
|
||||||
|
], [je_cv_os_unfair_lock])
|
||||||
|
if test "x${je_cv_os_unfair_lock}" = "xyes" ; then
|
||||||
|
AC_DEFINE([JEMALLOC_OS_UNFAIR_LOCK], [ ])
|
||||||
|
fi
|
||||||
|
|
||||||
dnl ============================================================================
|
dnl ============================================================================
|
||||||
dnl Check for spinlock(3) operations as provided on Darwin.
|
dnl Check for spinlock(3) operations as provided on Darwin.
|
||||||
|
|
||||||
@@ -1744,6 +1979,7 @@ AC_MSG_RESULT([])
|
|||||||
AC_MSG_RESULT([CONFIG : ${CONFIG}])
|
AC_MSG_RESULT([CONFIG : ${CONFIG}])
|
||||||
AC_MSG_RESULT([CC : ${CC}])
|
AC_MSG_RESULT([CC : ${CC}])
|
||||||
AC_MSG_RESULT([CFLAGS : ${CFLAGS}])
|
AC_MSG_RESULT([CFLAGS : ${CFLAGS}])
|
||||||
|
AC_MSG_RESULT([EXTRA_CFLAGS : ${EXTRA_CFLAGS}])
|
||||||
AC_MSG_RESULT([CPPFLAGS : ${CPPFLAGS}])
|
AC_MSG_RESULT([CPPFLAGS : ${CPPFLAGS}])
|
||||||
AC_MSG_RESULT([LDFLAGS : ${LDFLAGS}])
|
AC_MSG_RESULT([LDFLAGS : ${LDFLAGS}])
|
||||||
AC_MSG_RESULT([EXTRA_LDFLAGS : ${EXTRA_LDFLAGS}])
|
AC_MSG_RESULT([EXTRA_LDFLAGS : ${EXTRA_LDFLAGS}])
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||||
<xsl:import href="@XSLROOT@/html/docbook.xsl"/>
|
<xsl:import href="@XSLROOT@/html/docbook.xsl"/>
|
||||||
<xsl:import href="@abs_srcroot@doc/stylesheet.xsl"/>
|
<xsl:import href="@abs_srcroot@doc/stylesheet.xsl"/>
|
||||||
|
<xsl:output method="xml" encoding="utf-8"/>
|
||||||
</xsl:stylesheet>
|
</xsl:stylesheet>
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
<title>LIBRARY</title>
|
<title>LIBRARY</title>
|
||||||
<para>This manual describes jemalloc @jemalloc_version@. More information
|
<para>This manual describes jemalloc @jemalloc_version@. More information
|
||||||
can be found at the <ulink
|
can be found at the <ulink
|
||||||
url="http://www.canonware.com/jemalloc/">jemalloc website</ulink>.</para>
|
url="http://jemalloc.net/">jemalloc website</ulink>.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<title>SYNOPSIS</title>
|
<title>SYNOPSIS</title>
|
||||||
@@ -180,20 +180,20 @@
|
|||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Standard API</title>
|
<title>Standard API</title>
|
||||||
|
|
||||||
<para>The <function>malloc<parameter/></function> function allocates
|
<para>The <function>malloc()</function> function allocates
|
||||||
<parameter>size</parameter> bytes of uninitialized memory. The allocated
|
<parameter>size</parameter> bytes of uninitialized memory. The allocated
|
||||||
space is suitably aligned (after possible pointer coercion) for storage
|
space is suitably aligned (after possible pointer coercion) for storage
|
||||||
of any type of object.</para>
|
of any type of object.</para>
|
||||||
|
|
||||||
<para>The <function>calloc<parameter/></function> function allocates
|
<para>The <function>calloc()</function> function allocates
|
||||||
space for <parameter>number</parameter> objects, each
|
space for <parameter>number</parameter> objects, each
|
||||||
<parameter>size</parameter> bytes in length. The result is identical to
|
<parameter>size</parameter> bytes in length. The result is identical to
|
||||||
calling <function>malloc<parameter/></function> with an argument of
|
calling <function>malloc()</function> with an argument of
|
||||||
<parameter>number</parameter> * <parameter>size</parameter>, with the
|
<parameter>number</parameter> * <parameter>size</parameter>, with the
|
||||||
exception that the allocated memory is explicitly initialized to zero
|
exception that the allocated memory is explicitly initialized to zero
|
||||||
bytes.</para>
|
bytes.</para>
|
||||||
|
|
||||||
<para>The <function>posix_memalign<parameter/></function> function
|
<para>The <function>posix_memalign()</function> function
|
||||||
allocates <parameter>size</parameter> bytes of memory such that the
|
allocates <parameter>size</parameter> bytes of memory such that the
|
||||||
allocation's base address is a multiple of
|
allocation's base address is a multiple of
|
||||||
<parameter>alignment</parameter>, and returns the allocation in the value
|
<parameter>alignment</parameter>, and returns the allocation in the value
|
||||||
@@ -201,7 +201,7 @@
|
|||||||
<parameter>alignment</parameter> must be a power of 2 at least as large as
|
<parameter>alignment</parameter> must be a power of 2 at least as large as
|
||||||
<code language="C">sizeof(<type>void *</type>)</code>.</para>
|
<code language="C">sizeof(<type>void *</type>)</code>.</para>
|
||||||
|
|
||||||
<para>The <function>aligned_alloc<parameter/></function> function
|
<para>The <function>aligned_alloc()</function> function
|
||||||
allocates <parameter>size</parameter> bytes of memory such that the
|
allocates <parameter>size</parameter> bytes of memory such that the
|
||||||
allocation's base address is a multiple of
|
allocation's base address is a multiple of
|
||||||
<parameter>alignment</parameter>. The requested
|
<parameter>alignment</parameter>. The requested
|
||||||
@@ -209,7 +209,7 @@
|
|||||||
undefined if <parameter>size</parameter> is not an integral multiple of
|
undefined if <parameter>size</parameter> is not an integral multiple of
|
||||||
<parameter>alignment</parameter>.</para>
|
<parameter>alignment</parameter>.</para>
|
||||||
|
|
||||||
<para>The <function>realloc<parameter/></function> function changes the
|
<para>The <function>realloc()</function> function changes the
|
||||||
size of the previously allocated memory referenced by
|
size of the previously allocated memory referenced by
|
||||||
<parameter>ptr</parameter> to <parameter>size</parameter> bytes. The
|
<parameter>ptr</parameter> to <parameter>size</parameter> bytes. The
|
||||||
contents of the memory are unchanged up to the lesser of the new and old
|
contents of the memory are unchanged up to the lesser of the new and old
|
||||||
@@ -217,26 +217,26 @@
|
|||||||
portion of the memory are undefined. Upon success, the memory referenced
|
portion of the memory are undefined. Upon success, the memory referenced
|
||||||
by <parameter>ptr</parameter> is freed and a pointer to the newly
|
by <parameter>ptr</parameter> is freed and a pointer to the newly
|
||||||
allocated memory is returned. Note that
|
allocated memory is returned. Note that
|
||||||
<function>realloc<parameter/></function> may move the memory allocation,
|
<function>realloc()</function> may move the memory allocation,
|
||||||
resulting in a different return value than <parameter>ptr</parameter>.
|
resulting in a different return value than <parameter>ptr</parameter>.
|
||||||
If <parameter>ptr</parameter> is <constant>NULL</constant>, the
|
If <parameter>ptr</parameter> is <constant>NULL</constant>, the
|
||||||
<function>realloc<parameter/></function> function behaves identically to
|
<function>realloc()</function> function behaves identically to
|
||||||
<function>malloc<parameter/></function> for the specified size.</para>
|
<function>malloc()</function> for the specified size.</para>
|
||||||
|
|
||||||
<para>The <function>free<parameter/></function> function causes the
|
<para>The <function>free()</function> function causes the
|
||||||
allocated memory referenced by <parameter>ptr</parameter> to be made
|
allocated memory referenced by <parameter>ptr</parameter> to be made
|
||||||
available for future allocations. If <parameter>ptr</parameter> is
|
available for future allocations. If <parameter>ptr</parameter> is
|
||||||
<constant>NULL</constant>, no action occurs.</para>
|
<constant>NULL</constant>, no action occurs.</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Non-standard API</title>
|
<title>Non-standard API</title>
|
||||||
<para>The <function>mallocx<parameter/></function>,
|
<para>The <function>mallocx()</function>,
|
||||||
<function>rallocx<parameter/></function>,
|
<function>rallocx()</function>,
|
||||||
<function>xallocx<parameter/></function>,
|
<function>xallocx()</function>,
|
||||||
<function>sallocx<parameter/></function>,
|
<function>sallocx()</function>,
|
||||||
<function>dallocx<parameter/></function>,
|
<function>dallocx()</function>,
|
||||||
<function>sdallocx<parameter/></function>, and
|
<function>sdallocx()</function>, and
|
||||||
<function>nallocx<parameter/></function> functions all have a
|
<function>nallocx()</function> functions all have a
|
||||||
<parameter>flags</parameter> argument that can be used to specify
|
<parameter>flags</parameter> argument that can be used to specify
|
||||||
options. The functions only check the options that are contextually
|
options. The functions only check the options that are contextually
|
||||||
relevant. Use bitwise or (<code language="C">|</code>) operations to
|
relevant. Use bitwise or (<code language="C">|</code>) operations to
|
||||||
@@ -307,19 +307,19 @@
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>The <function>mallocx<parameter/></function> function allocates at
|
<para>The <function>mallocx()</function> function allocates at
|
||||||
least <parameter>size</parameter> bytes of memory, and returns a pointer
|
least <parameter>size</parameter> bytes of memory, and returns a pointer
|
||||||
to the base address of the allocation. Behavior is undefined if
|
to the base address of the allocation. Behavior is undefined if
|
||||||
<parameter>size</parameter> is <constant>0</constant>.</para>
|
<parameter>size</parameter> is <constant>0</constant>.</para>
|
||||||
|
|
||||||
<para>The <function>rallocx<parameter/></function> function resizes the
|
<para>The <function>rallocx()</function> function resizes the
|
||||||
allocation at <parameter>ptr</parameter> to be at least
|
allocation at <parameter>ptr</parameter> to be at least
|
||||||
<parameter>size</parameter> bytes, and returns a pointer to the base
|
<parameter>size</parameter> bytes, and returns a pointer to the base
|
||||||
address of the resulting allocation, which may or may not have moved from
|
address of the resulting allocation, which may or may not have moved from
|
||||||
its original location. Behavior is undefined if
|
its original location. Behavior is undefined if
|
||||||
<parameter>size</parameter> is <constant>0</constant>.</para>
|
<parameter>size</parameter> is <constant>0</constant>.</para>
|
||||||
|
|
||||||
<para>The <function>xallocx<parameter/></function> function resizes the
|
<para>The <function>xallocx()</function> function resizes the
|
||||||
allocation at <parameter>ptr</parameter> in place to be at least
|
allocation at <parameter>ptr</parameter> in place to be at least
|
||||||
<parameter>size</parameter> bytes, and returns the real size of the
|
<parameter>size</parameter> bytes, and returns the real size of the
|
||||||
allocation. If <parameter>extra</parameter> is non-zero, an attempt is
|
allocation. If <parameter>extra</parameter> is non-zero, an attempt is
|
||||||
@@ -332,32 +332,32 @@
|
|||||||
language="C">(<parameter>size</parameter> + <parameter>extra</parameter>
|
language="C">(<parameter>size</parameter> + <parameter>extra</parameter>
|
||||||
> <constant>SIZE_T_MAX</constant>)</code>.</para>
|
> <constant>SIZE_T_MAX</constant>)</code>.</para>
|
||||||
|
|
||||||
<para>The <function>sallocx<parameter/></function> function returns the
|
<para>The <function>sallocx()</function> function returns the
|
||||||
real size of the allocation at <parameter>ptr</parameter>.</para>
|
real size of the allocation at <parameter>ptr</parameter>.</para>
|
||||||
|
|
||||||
<para>The <function>dallocx<parameter/></function> function causes the
|
<para>The <function>dallocx()</function> function causes the
|
||||||
memory referenced by <parameter>ptr</parameter> to be made available for
|
memory referenced by <parameter>ptr</parameter> to be made available for
|
||||||
future allocations.</para>
|
future allocations.</para>
|
||||||
|
|
||||||
<para>The <function>sdallocx<parameter/></function> function is an
|
<para>The <function>sdallocx()</function> function is an
|
||||||
extension of <function>dallocx<parameter/></function> with a
|
extension of <function>dallocx()</function> with a
|
||||||
<parameter>size</parameter> parameter to allow the caller to pass in the
|
<parameter>size</parameter> parameter to allow the caller to pass in the
|
||||||
allocation size as an optimization. The minimum valid input size is the
|
allocation size as an optimization. The minimum valid input size is the
|
||||||
original requested size of the allocation, and the maximum valid input
|
original requested size of the allocation, and the maximum valid input
|
||||||
size is the corresponding value returned by
|
size is the corresponding value returned by
|
||||||
<function>nallocx<parameter/></function> or
|
<function>nallocx()</function> or
|
||||||
<function>sallocx<parameter/></function>.</para>
|
<function>sallocx()</function>.</para>
|
||||||
|
|
||||||
<para>The <function>nallocx<parameter/></function> function allocates no
|
<para>The <function>nallocx()</function> function allocates no
|
||||||
memory, but it performs the same size computation as the
|
memory, but it performs the same size computation as the
|
||||||
<function>mallocx<parameter/></function> function, and returns the real
|
<function>mallocx()</function> function, and returns the real
|
||||||
size of the allocation that would result from the equivalent
|
size of the allocation that would result from the equivalent
|
||||||
<function>mallocx<parameter/></function> function call, or
|
<function>mallocx()</function> function call, or
|
||||||
<constant>0</constant> if the inputs exceed the maximum supported size
|
<constant>0</constant> if the inputs exceed the maximum supported size
|
||||||
class and/or alignment. Behavior is undefined if
|
class and/or alignment. Behavior is undefined if
|
||||||
<parameter>size</parameter> is <constant>0</constant>.</para>
|
<parameter>size</parameter> is <constant>0</constant>.</para>
|
||||||
|
|
||||||
<para>The <function>mallctl<parameter/></function> function provides a
|
<para>The <function>mallctl()</function> function provides a
|
||||||
general interface for introspecting the memory allocator, as well as
|
general interface for introspecting the memory allocator, as well as
|
||||||
setting modifiable parameters and triggering actions. The
|
setting modifiable parameters and triggering actions. The
|
||||||
period-separated <parameter>name</parameter> argument specifies a
|
period-separated <parameter>name</parameter> argument specifies a
|
||||||
@@ -372,12 +372,12 @@
|
|||||||
<parameter>newlen</parameter>; otherwise pass <constant>NULL</constant>
|
<parameter>newlen</parameter>; otherwise pass <constant>NULL</constant>
|
||||||
and <constant>0</constant>.</para>
|
and <constant>0</constant>.</para>
|
||||||
|
|
||||||
<para>The <function>mallctlnametomib<parameter/></function> function
|
<para>The <function>mallctlnametomib()</function> function
|
||||||
provides a way to avoid repeated name lookups for applications that
|
provides a way to avoid repeated name lookups for applications that
|
||||||
repeatedly query the same portion of the namespace, by translating a name
|
repeatedly query the same portion of the namespace, by translating a name
|
||||||
to a “Management Information Base” (MIB) that can be passed
|
to a <quote>Management Information Base</quote> (MIB) that can be passed
|
||||||
repeatedly to <function>mallctlbymib<parameter/></function>. Upon
|
repeatedly to <function>mallctlbymib()</function>. Upon
|
||||||
successful return from <function>mallctlnametomib<parameter/></function>,
|
successful return from <function>mallctlnametomib()</function>,
|
||||||
<parameter>mibp</parameter> contains an array of
|
<parameter>mibp</parameter> contains an array of
|
||||||
<parameter>*miblenp</parameter> integers, where
|
<parameter>*miblenp</parameter> integers, where
|
||||||
<parameter>*miblenp</parameter> is the lesser of the number of components
|
<parameter>*miblenp</parameter> is the lesser of the number of components
|
||||||
@@ -406,43 +406,44 @@ for (i = 0; i < nbins; i++) {
|
|||||||
|
|
||||||
mib[2] = i;
|
mib[2] = i;
|
||||||
len = sizeof(bin_size);
|
len = sizeof(bin_size);
|
||||||
mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0);
|
mallctlbymib(mib, miblen, (void *)&bin_size, &len, NULL, 0);
|
||||||
/* Do something with bin_size... */
|
/* Do something with bin_size... */
|
||||||
}]]></programlisting></para>
|
}]]></programlisting></para>
|
||||||
|
|
||||||
<para>The <function>malloc_stats_print<parameter/></function> function
|
<para>The <function>malloc_stats_print()</function> function writes
|
||||||
writes human-readable summary statistics via the
|
summary statistics via the <parameter>write_cb</parameter> callback
|
||||||
<parameter>write_cb</parameter> callback function pointer and
|
function pointer and <parameter>cbopaque</parameter> data passed to
|
||||||
<parameter>cbopaque</parameter> data passed to
|
<parameter>write_cb</parameter>, or <function>malloc_message()</function>
|
||||||
<parameter>write_cb</parameter>, or
|
if <parameter>write_cb</parameter> is <constant>NULL</constant>. The
|
||||||
<function>malloc_message<parameter/></function> if
|
statistics are presented in human-readable form unless <quote>J</quote> is
|
||||||
<parameter>write_cb</parameter> is <constant>NULL</constant>. This
|
specified as a character within the <parameter>opts</parameter> string, in
|
||||||
function can be called repeatedly. General information that never
|
which case the statistics are presented in <ulink
|
||||||
changes during execution can be omitted by specifying "g" as a character
|
url="http://www.json.org/">JSON format</ulink>. This function can be
|
||||||
|
called repeatedly. General information that never changes during
|
||||||
|
execution can be omitted by specifying <quote>g</quote> as a character
|
||||||
within the <parameter>opts</parameter> string. Note that
|
within the <parameter>opts</parameter> string. Note that
|
||||||
<function>malloc_message<parameter/></function> uses the
|
<function>malloc_message()</function> uses the
|
||||||
<function>mallctl*<parameter/></function> functions internally, so
|
<function>mallctl*()</function> functions internally, so inconsistent
|
||||||
inconsistent statistics can be reported if multiple threads use these
|
statistics can be reported if multiple threads use these functions
|
||||||
functions simultaneously. If <option>--enable-stats</option> is
|
simultaneously. If <option>--enable-stats</option> is specified during
|
||||||
specified during configuration, “m” and “a” can
|
configuration, <quote>m</quote> and <quote>a</quote> can be specified to
|
||||||
be specified to omit merged arena and per arena statistics, respectively;
|
omit merged arena and per arena statistics, respectively;
|
||||||
“b”, “l”, and “h” can be specified to
|
<quote>b</quote>, <quote>l</quote>, and <quote>h</quote> can be specified
|
||||||
omit per size class statistics for bins, large objects, and huge objects,
|
to omit per size class statistics for bins, large objects, and huge
|
||||||
respectively. Unrecognized characters are silently ignored. Note that
|
objects, respectively. Unrecognized characters are silently ignored.
|
||||||
thread caching may prevent some statistics from being completely up to
|
Note that thread caching may prevent some statistics from being completely
|
||||||
date, since extra locking would be required to merge counters that track
|
up to date, since extra locking would be required to merge counters that
|
||||||
thread cache operations.
|
track thread cache operations.</para>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>The <function>malloc_usable_size<parameter/></function> function
|
<para>The <function>malloc_usable_size()</function> function
|
||||||
returns the usable size of the allocation pointed to by
|
returns the usable size of the allocation pointed to by
|
||||||
<parameter>ptr</parameter>. The return value may be larger than the size
|
<parameter>ptr</parameter>. The return value may be larger than the size
|
||||||
that was requested during allocation. The
|
that was requested during allocation. The
|
||||||
<function>malloc_usable_size<parameter/></function> function is not a
|
<function>malloc_usable_size()</function> function is not a
|
||||||
mechanism for in-place <function>realloc<parameter/></function>; rather
|
mechanism for in-place <function>realloc()</function>; rather
|
||||||
it is provided solely as a tool for introspection purposes. Any
|
it is provided solely as a tool for introspection purposes. Any
|
||||||
discrepancy between the requested allocation size and the size reported
|
discrepancy between the requested allocation size and the size reported
|
||||||
by <function>malloc_usable_size<parameter/></function> should not be
|
by <function>malloc_usable_size()</function> should not be
|
||||||
depended on, since such behavior is entirely implementation-dependent.
|
depended on, since such behavior is entirely implementation-dependent.
|
||||||
</para>
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
@@ -455,12 +456,12 @@ for (i = 0; i < nbins; i++) {
|
|||||||
|
|
||||||
<para>The string specified via <option>--with-malloc-conf</option>, the
|
<para>The string specified via <option>--with-malloc-conf</option>, the
|
||||||
string pointed to by the global variable <varname>malloc_conf</varname>, the
|
string pointed to by the global variable <varname>malloc_conf</varname>, the
|
||||||
“name” of the file referenced by the symbolic link named
|
<quote>name</quote> of the file referenced by the symbolic link named
|
||||||
<filename class="symlink">/etc/malloc.conf</filename>, and the value of the
|
<filename class="symlink">/etc/malloc.conf</filename>, and the value of the
|
||||||
environment variable <envar>MALLOC_CONF</envar>, will be interpreted, in
|
environment variable <envar>MALLOC_CONF</envar>, will be interpreted, in
|
||||||
that order, from left to right as options. Note that
|
that order, from left to right as options. Note that
|
||||||
<varname>malloc_conf</varname> may be read before
|
<varname>malloc_conf</varname> may be read before
|
||||||
<function>main<parameter/></function> is entered, so the declaration of
|
<function>main()</function> is entered, so the declaration of
|
||||||
<varname>malloc_conf</varname> should specify an initializer that contains
|
<varname>malloc_conf</varname> should specify an initializer that contains
|
||||||
the final value to be read by jemalloc. <option>--with-malloc-conf</option>
|
the final value to be read by jemalloc. <option>--with-malloc-conf</option>
|
||||||
and <varname>malloc_conf</varname> are compile-time mechanisms, whereas
|
and <varname>malloc_conf</varname> are compile-time mechanisms, whereas
|
||||||
@@ -549,14 +550,14 @@ for (i = 0; i < nbins; i++) {
|
|||||||
nearest multiple of the cacheline size, or specify cacheline alignment when
|
nearest multiple of the cacheline size, or specify cacheline alignment when
|
||||||
allocating.</para>
|
allocating.</para>
|
||||||
|
|
||||||
<para>The <function>realloc<parameter/></function>,
|
<para>The <function>realloc()</function>,
|
||||||
<function>rallocx<parameter/></function>, and
|
<function>rallocx()</function>, and
|
||||||
<function>xallocx<parameter/></function> functions may resize allocations
|
<function>xallocx()</function> functions may resize allocations
|
||||||
without moving them under limited circumstances. Unlike the
|
without moving them under limited circumstances. Unlike the
|
||||||
<function>*allocx<parameter/></function> API, the standard API does not
|
<function>*allocx()</function> API, the standard API does not
|
||||||
officially round up the usable size of an allocation to the nearest size
|
officially round up the usable size of an allocation to the nearest size
|
||||||
class, so technically it is necessary to call
|
class, so technically it is necessary to call
|
||||||
<function>realloc<parameter/></function> to grow e.g. a 9-byte allocation to
|
<function>realloc()</function> to grow e.g. a 9-byte allocation to
|
||||||
16 bytes, or shrink a 16-byte allocation to 9 bytes. Growth and shrinkage
|
16 bytes, or shrink a 16-byte allocation to 9 bytes. Growth and shrinkage
|
||||||
trivially succeeds in place as long as the pre-size and post-size both round
|
trivially succeeds in place as long as the pre-size and post-size both round
|
||||||
up to the same size class. No other API guarantees are made regarding
|
up to the same size class. No other API guarantees are made regarding
|
||||||
@@ -702,7 +703,7 @@ for (i = 0; i < nbins; i++) {
|
|||||||
<refsect1 id="mallctl_namespace">
|
<refsect1 id="mallctl_namespace">
|
||||||
<title>MALLCTL NAMESPACE</title>
|
<title>MALLCTL NAMESPACE</title>
|
||||||
<para>The following names are defined in the namespace accessible via the
|
<para>The following names are defined in the namespace accessible via the
|
||||||
<function>mallctl*<parameter/></function> functions. Value types are
|
<function>mallctl*()</function> functions. Value types are
|
||||||
specified in parentheses, their readable/writable statuses are encoded as
|
specified in parentheses, their readable/writable statuses are encoded as
|
||||||
<literal>rw</literal>, <literal>r-</literal>, <literal>-w</literal>, or
|
<literal>rw</literal>, <literal>r-</literal>, <literal>-w</literal>, or
|
||||||
<literal>--</literal>, and required build configuration flags follow, if
|
<literal>--</literal>, and required build configuration flags follow, if
|
||||||
@@ -733,7 +734,7 @@ for (i = 0; i < nbins; i++) {
|
|||||||
<literal>rw</literal>
|
<literal>rw</literal>
|
||||||
</term>
|
</term>
|
||||||
<listitem><para>If a value is passed in, refresh the data from which
|
<listitem><para>If a value is passed in, refresh the data from which
|
||||||
the <function>mallctl*<parameter/></function> functions report values,
|
the <function>mallctl*()</function> functions report values,
|
||||||
and increment the epoch. Return the current epoch. This is useful for
|
and increment the epoch. Return the current epoch. This is useful for
|
||||||
detecting whether another thread caused a refresh.</para></listitem>
|
detecting whether another thread caused a refresh.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -917,12 +918,12 @@ for (i = 0; i < nbins; i++) {
|
|||||||
settings are supported if
|
settings are supported if
|
||||||
<citerefentry><refentrytitle>sbrk</refentrytitle>
|
<citerefentry><refentrytitle>sbrk</refentrytitle>
|
||||||
<manvolnum>2</manvolnum></citerefentry> is supported by the operating
|
<manvolnum>2</manvolnum></citerefentry> is supported by the operating
|
||||||
system: “disabled”, “primary”, and
|
system: <quote>disabled</quote>, <quote>primary</quote>, and
|
||||||
“secondary”; otherwise only “disabled” is
|
<quote>secondary</quote>; otherwise only <quote>disabled</quote> is
|
||||||
supported. The default is “secondary” if
|
supported. The default is <quote>secondary</quote> if
|
||||||
<citerefentry><refentrytitle>sbrk</refentrytitle>
|
<citerefentry><refentrytitle>sbrk</refentrytitle>
|
||||||
<manvolnum>2</manvolnum></citerefentry> is supported by the operating
|
<manvolnum>2</manvolnum></citerefentry> is supported by the operating
|
||||||
system; “disabled” otherwise.
|
system; <quote>disabled</quote> otherwise.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
@@ -1013,19 +1014,19 @@ for (i = 0; i < nbins; i++) {
|
|||||||
<literal>r-</literal>
|
<literal>r-</literal>
|
||||||
</term>
|
</term>
|
||||||
<listitem><para>Enable/disable statistics printing at exit. If
|
<listitem><para>Enable/disable statistics printing at exit. If
|
||||||
enabled, the <function>malloc_stats_print<parameter/></function>
|
enabled, the <function>malloc_stats_print()</function>
|
||||||
function is called at program exit via an
|
function is called at program exit via an
|
||||||
<citerefentry><refentrytitle>atexit</refentrytitle>
|
<citerefentry><refentrytitle>atexit</refentrytitle>
|
||||||
<manvolnum>3</manvolnum></citerefentry> function. If
|
<manvolnum>3</manvolnum></citerefentry> function. If
|
||||||
<option>--enable-stats</option> is specified during configuration, this
|
<option>--enable-stats</option> is specified during configuration, this
|
||||||
has the potential to cause deadlock for a multi-threaded process that
|
has the potential to cause deadlock for a multi-threaded process that
|
||||||
exits while one or more threads are executing in the memory allocation
|
exits while one or more threads are executing in the memory allocation
|
||||||
functions. Furthermore, <function>atexit<parameter/></function> may
|
functions. Furthermore, <function>atexit()</function> may
|
||||||
allocate memory during application initialization and then deadlock
|
allocate memory during application initialization and then deadlock
|
||||||
internally when jemalloc in turn calls
|
internally when jemalloc in turn calls
|
||||||
<function>atexit<parameter/></function>, so this option is not
|
<function>atexit()</function>, so this option is not
|
||||||
universally usable (though the application can register its own
|
universally usable (though the application can register its own
|
||||||
<function>atexit<parameter/></function> function with equivalent
|
<function>atexit()</function> function with equivalent
|
||||||
functionality). Therefore, this option should only be used with care;
|
functionality). Therefore, this option should only be used with care;
|
||||||
it is primarily intended as a performance tuning aid during application
|
it is primarily intended as a performance tuning aid during application
|
||||||
development. This option is disabled by default.</para></listitem>
|
development. This option is disabled by default.</para></listitem>
|
||||||
@@ -1038,15 +1039,16 @@ for (i = 0; i < nbins; i++) {
|
|||||||
<literal>r-</literal>
|
<literal>r-</literal>
|
||||||
[<option>--enable-fill</option>]
|
[<option>--enable-fill</option>]
|
||||||
</term>
|
</term>
|
||||||
<listitem><para>Junk filling. If set to "alloc", each byte of
|
<listitem><para>Junk filling. If set to <quote>alloc</quote>, each byte
|
||||||
uninitialized allocated memory will be initialized to
|
of uninitialized allocated memory will be initialized to
|
||||||
<literal>0xa5</literal>. If set to "free", all deallocated memory will
|
<literal>0xa5</literal>. If set to <quote>free</quote>, all deallocated
|
||||||
be initialized to <literal>0x5a</literal>. If set to "true", both
|
memory will be initialized to <literal>0x5a</literal>. If set to
|
||||||
allocated and deallocated memory will be initialized, and if set to
|
<quote>true</quote>, both allocated and deallocated memory will be
|
||||||
"false", junk filling be disabled entirely. This is intended for
|
initialized, and if set to <quote>false</quote>, junk filling be
|
||||||
debugging and will impact performance negatively. This option is
|
disabled entirely. This is intended for debugging and will impact
|
||||||
"false" by default unless <option>--enable-debug</option> is specified
|
performance negatively. This option is <quote>false</quote> by default
|
||||||
during configuration, in which case it is "true" by default unless
|
unless <option>--enable-debug</option> is specified during
|
||||||
|
configuration, in which case it is <quote>true</quote> by default unless
|
||||||
running inside <ulink
|
running inside <ulink
|
||||||
url="http://valgrind.org/">Valgrind</ulink>.</para></listitem>
|
url="http://valgrind.org/">Valgrind</ulink>.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -1101,8 +1103,8 @@ for (i = 0; i < nbins; i++) {
|
|||||||
<listitem><para>Zero filling enabled/disabled. If enabled, each byte
|
<listitem><para>Zero filling enabled/disabled. If enabled, each byte
|
||||||
of uninitialized allocated memory will be initialized to 0. Note that
|
of uninitialized allocated memory will be initialized to 0. Note that
|
||||||
this initialization only happens once for each byte, so
|
this initialization only happens once for each byte, so
|
||||||
<function>realloc<parameter/></function> and
|
<function>realloc()</function> and
|
||||||
<function>rallocx<parameter/></function> calls do not zero memory that
|
<function>rallocx()</function> calls do not zero memory that
|
||||||
was previously allocated. This is intended for debugging and will
|
was previously allocated. This is intended for debugging and will
|
||||||
impact performance negatively. This option is disabled by default.
|
impact performance negatively. This option is disabled by default.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
@@ -1325,11 +1327,11 @@ malloc_conf = "xmalloc:true";]]></programlisting>
|
|||||||
<filename><prefix>.<pid>.<seq>.f.heap</filename>,
|
<filename><prefix>.<pid>.<seq>.f.heap</filename>,
|
||||||
where <literal><prefix></literal> is controlled by the <link
|
where <literal><prefix></literal> is controlled by the <link
|
||||||
linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link>
|
linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link>
|
||||||
option. Note that <function>atexit<parameter/></function> may allocate
|
option. Note that <function>atexit()</function> may allocate
|
||||||
memory during application initialization and then deadlock internally
|
memory during application initialization and then deadlock internally
|
||||||
when jemalloc in turn calls <function>atexit<parameter/></function>, so
|
when jemalloc in turn calls <function>atexit()</function>, so
|
||||||
this option is not universally usable (though the application can
|
this option is not universally usable (though the application can
|
||||||
register its own <function>atexit<parameter/></function> function with
|
register its own <function>atexit()</function> function with
|
||||||
equivalent functionality). This option is disabled by
|
equivalent functionality). This option is disabled by
|
||||||
default.</para></listitem>
|
default.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -1388,7 +1390,7 @@ malloc_conf = "xmalloc:true";]]></programlisting>
|
|||||||
<link
|
<link
|
||||||
linkend="thread.allocated"><mallctl>thread.allocated</mallctl></link>
|
linkend="thread.allocated"><mallctl>thread.allocated</mallctl></link>
|
||||||
mallctl. This is useful for avoiding the overhead of repeated
|
mallctl. This is useful for avoiding the overhead of repeated
|
||||||
<function>mallctl*<parameter/></function> calls.</para></listitem>
|
<function>mallctl*()</function> calls.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="thread.deallocated">
|
<varlistentry id="thread.deallocated">
|
||||||
@@ -1415,7 +1417,7 @@ malloc_conf = "xmalloc:true";]]></programlisting>
|
|||||||
<link
|
<link
|
||||||
linkend="thread.deallocated"><mallctl>thread.deallocated</mallctl></link>
|
linkend="thread.deallocated"><mallctl>thread.deallocated</mallctl></link>
|
||||||
mallctl. This is useful for avoiding the overhead of repeated
|
mallctl. This is useful for avoiding the overhead of repeated
|
||||||
<function>mallctl*<parameter/></function> calls.</para></listitem>
|
<function>mallctl*()</function> calls.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="thread.tcache.enabled">
|
<varlistentry id="thread.tcache.enabled">
|
||||||
@@ -2734,7 +2736,7 @@ MAPPED_LIBRARIES:
|
|||||||
of run-time assertions that catch application errors such as double-free,
|
of run-time assertions that catch application errors such as double-free,
|
||||||
write-after-free, etc.</para>
|
write-after-free, etc.</para>
|
||||||
|
|
||||||
<para>Programs often accidentally depend on “uninitialized”
|
<para>Programs often accidentally depend on <quote>uninitialized</quote>
|
||||||
memory actually being filled with zero bytes. Junk filling
|
memory actually being filled with zero bytes. Junk filling
|
||||||
(see the <link linkend="opt.junk"><mallctl>opt.junk</mallctl></link>
|
(see the <link linkend="opt.junk"><mallctl>opt.junk</mallctl></link>
|
||||||
option) tends to expose such bugs in the form of obviously incorrect
|
option) tends to expose such bugs in the form of obviously incorrect
|
||||||
@@ -2763,29 +2765,29 @@ MAPPED_LIBRARIES:
|
|||||||
to override the function which emits the text strings forming the errors
|
to override the function which emits the text strings forming the errors
|
||||||
and warnings if for some reason the <constant>STDERR_FILENO</constant> file
|
and warnings if for some reason the <constant>STDERR_FILENO</constant> file
|
||||||
descriptor is not suitable for this.
|
descriptor is not suitable for this.
|
||||||
<function>malloc_message<parameter/></function> takes the
|
<function>malloc_message()</function> takes the
|
||||||
<parameter>cbopaque</parameter> pointer argument that is
|
<parameter>cbopaque</parameter> pointer argument that is
|
||||||
<constant>NULL</constant> unless overridden by the arguments in a call to
|
<constant>NULL</constant> unless overridden by the arguments in a call to
|
||||||
<function>malloc_stats_print<parameter/></function>, followed by a string
|
<function>malloc_stats_print()</function>, followed by a string
|
||||||
pointer. Please note that doing anything which tries to allocate memory in
|
pointer. Please note that doing anything which tries to allocate memory in
|
||||||
this function is likely to result in a crash or deadlock.</para>
|
this function is likely to result in a crash or deadlock.</para>
|
||||||
|
|
||||||
<para>All messages are prefixed by
|
<para>All messages are prefixed by
|
||||||
“<computeroutput><jemalloc>: </computeroutput>”.</para>
|
<quote><computeroutput><jemalloc>: </computeroutput></quote>.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
<refsect1 id="return_values">
|
<refsect1 id="return_values">
|
||||||
<title>RETURN VALUES</title>
|
<title>RETURN VALUES</title>
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Standard API</title>
|
<title>Standard API</title>
|
||||||
<para>The <function>malloc<parameter/></function> and
|
<para>The <function>malloc()</function> and
|
||||||
<function>calloc<parameter/></function> functions return a pointer to the
|
<function>calloc()</function> functions return a pointer to the
|
||||||
allocated memory if successful; otherwise a <constant>NULL</constant>
|
allocated memory if successful; otherwise a <constant>NULL</constant>
|
||||||
pointer is returned and <varname>errno</varname> is set to
|
pointer is returned and <varname>errno</varname> is set to
|
||||||
<errorname>ENOMEM</errorname>.</para>
|
<errorname>ENOMEM</errorname>.</para>
|
||||||
|
|
||||||
<para>The <function>posix_memalign<parameter/></function> function
|
<para>The <function>posix_memalign()</function> function
|
||||||
returns the value 0 if successful; otherwise it returns an error value.
|
returns the value 0 if successful; otherwise it returns an error value.
|
||||||
The <function>posix_memalign<parameter/></function> function will fail
|
The <function>posix_memalign()</function> function will fail
|
||||||
if:
|
if:
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
@@ -2804,11 +2806,11 @@ MAPPED_LIBRARIES:
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>The <function>aligned_alloc<parameter/></function> function returns
|
<para>The <function>aligned_alloc()</function> function returns
|
||||||
a pointer to the allocated memory if successful; otherwise a
|
a pointer to the allocated memory if successful; otherwise a
|
||||||
<constant>NULL</constant> pointer is returned and
|
<constant>NULL</constant> pointer is returned and
|
||||||
<varname>errno</varname> is set. The
|
<varname>errno</varname> is set. The
|
||||||
<function>aligned_alloc<parameter/></function> function will fail if:
|
<function>aligned_alloc()</function> function will fail if:
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><errorname>EINVAL</errorname></term>
|
<term><errorname>EINVAL</errorname></term>
|
||||||
@@ -2825,44 +2827,44 @@ MAPPED_LIBRARIES:
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>The <function>realloc<parameter/></function> function returns a
|
<para>The <function>realloc()</function> function returns a
|
||||||
pointer, possibly identical to <parameter>ptr</parameter>, to the
|
pointer, possibly identical to <parameter>ptr</parameter>, to the
|
||||||
allocated memory if successful; otherwise a <constant>NULL</constant>
|
allocated memory if successful; otherwise a <constant>NULL</constant>
|
||||||
pointer is returned, and <varname>errno</varname> is set to
|
pointer is returned, and <varname>errno</varname> is set to
|
||||||
<errorname>ENOMEM</errorname> if the error was the result of an
|
<errorname>ENOMEM</errorname> if the error was the result of an
|
||||||
allocation failure. The <function>realloc<parameter/></function>
|
allocation failure. The <function>realloc()</function>
|
||||||
function always leaves the original buffer intact when an error occurs.
|
function always leaves the original buffer intact when an error occurs.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>The <function>free<parameter/></function> function returns no
|
<para>The <function>free()</function> function returns no
|
||||||
value.</para>
|
value.</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Non-standard API</title>
|
<title>Non-standard API</title>
|
||||||
<para>The <function>mallocx<parameter/></function> and
|
<para>The <function>mallocx()</function> and
|
||||||
<function>rallocx<parameter/></function> functions return a pointer to
|
<function>rallocx()</function> functions return a pointer to
|
||||||
the allocated memory if successful; otherwise a <constant>NULL</constant>
|
the allocated memory if successful; otherwise a <constant>NULL</constant>
|
||||||
pointer is returned to indicate insufficient contiguous memory was
|
pointer is returned to indicate insufficient contiguous memory was
|
||||||
available to service the allocation request. </para>
|
available to service the allocation request. </para>
|
||||||
|
|
||||||
<para>The <function>xallocx<parameter/></function> function returns the
|
<para>The <function>xallocx()</function> function returns the
|
||||||
real size of the resulting resized allocation pointed to by
|
real size of the resulting resized allocation pointed to by
|
||||||
<parameter>ptr</parameter>, which is a value less than
|
<parameter>ptr</parameter>, which is a value less than
|
||||||
<parameter>size</parameter> if the allocation could not be adequately
|
<parameter>size</parameter> if the allocation could not be adequately
|
||||||
grown in place. </para>
|
grown in place. </para>
|
||||||
|
|
||||||
<para>The <function>sallocx<parameter/></function> function returns the
|
<para>The <function>sallocx()</function> function returns the
|
||||||
real size of the allocation pointed to by <parameter>ptr</parameter>.
|
real size of the allocation pointed to by <parameter>ptr</parameter>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>The <function>nallocx<parameter/></function> returns the real size
|
<para>The <function>nallocx()</function> returns the real size
|
||||||
that would result from a successful equivalent
|
that would result from a successful equivalent
|
||||||
<function>mallocx<parameter/></function> function call, or zero if
|
<function>mallocx()</function> function call, or zero if
|
||||||
insufficient memory is available to perform the size computation. </para>
|
insufficient memory is available to perform the size computation. </para>
|
||||||
|
|
||||||
<para>The <function>mallctl<parameter/></function>,
|
<para>The <function>mallctl()</function>,
|
||||||
<function>mallctlnametomib<parameter/></function>, and
|
<function>mallctlnametomib()</function>, and
|
||||||
<function>mallctlbymib<parameter/></function> functions return 0 on
|
<function>mallctlbymib()</function> functions return 0 on
|
||||||
success; otherwise they return an error value. The functions will fail
|
success; otherwise they return an error value. The functions will fail
|
||||||
if:
|
if:
|
||||||
<variablelist>
|
<variablelist>
|
||||||
@@ -2898,13 +2900,13 @@ MAPPED_LIBRARIES:
|
|||||||
<term><errorname>EFAULT</errorname></term>
|
<term><errorname>EFAULT</errorname></term>
|
||||||
|
|
||||||
<listitem><para>An interface with side effects failed in some way
|
<listitem><para>An interface with side effects failed in some way
|
||||||
not directly related to <function>mallctl*<parameter/></function>
|
not directly related to <function>mallctl*()</function>
|
||||||
read/write processing.</para></listitem>
|
read/write processing.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>The <function>malloc_usable_size<parameter/></function> function
|
<para>The <function>malloc_usable_size()</function> function
|
||||||
returns the usable size of the allocation pointed to by
|
returns the usable size of the allocation pointed to by
|
||||||
<parameter>ptr</parameter>. </para>
|
<parameter>ptr</parameter>. </para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
@@ -2952,13 +2954,13 @@ malloc_conf = "lg_chunk:24";]]></programlisting></para>
|
|||||||
</refsect1>
|
</refsect1>
|
||||||
<refsect1 id="standards">
|
<refsect1 id="standards">
|
||||||
<title>STANDARDS</title>
|
<title>STANDARDS</title>
|
||||||
<para>The <function>malloc<parameter/></function>,
|
<para>The <function>malloc()</function>,
|
||||||
<function>calloc<parameter/></function>,
|
<function>calloc()</function>,
|
||||||
<function>realloc<parameter/></function>, and
|
<function>realloc()</function>, and
|
||||||
<function>free<parameter/></function> functions conform to ISO/IEC
|
<function>free()</function> functions conform to ISO/IEC
|
||||||
9899:1990 (“ISO C90”).</para>
|
9899:1990 (<quote>ISO C90</quote>).</para>
|
||||||
|
|
||||||
<para>The <function>posix_memalign<parameter/></function> function conforms
|
<para>The <function>posix_memalign()</function> function conforms
|
||||||
to IEEE Std 1003.1-2001 (“POSIX.1”).</para>
|
to IEEE Std 1003.1-2001 (<quote>POSIX.1</quote>).</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
<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="funcsynopsis.style">ansi</xsl:param>
|
||||||
<xsl:param name="function.parens" select="1"/>
|
<xsl:param name="function.parens" select="0"/>
|
||||||
|
<xsl:template match="function">
|
||||||
|
<xsl:call-template name="inline.monoseq"/>
|
||||||
|
</xsl:template>
|
||||||
<xsl:template match="mallctl">
|
<xsl:template match="mallctl">
|
||||||
"<xsl:call-template name="inline.monoseq"/>"
|
<quote><xsl:call-template name="inline.monoseq"/></quote>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
</xsl:stylesheet>
|
</xsl:stylesheet>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ typedef struct arena_chunk_map_bits_s arena_chunk_map_bits_t;
|
|||||||
typedef struct arena_chunk_map_misc_s arena_chunk_map_misc_t;
|
typedef struct arena_chunk_map_misc_s arena_chunk_map_misc_t;
|
||||||
typedef struct arena_chunk_s arena_chunk_t;
|
typedef struct arena_chunk_s arena_chunk_t;
|
||||||
typedef struct arena_bin_info_s arena_bin_info_t;
|
typedef struct arena_bin_info_s arena_bin_info_t;
|
||||||
|
typedef struct arena_decay_s arena_decay_t;
|
||||||
typedef struct arena_bin_s arena_bin_t;
|
typedef struct arena_bin_s arena_bin_t;
|
||||||
typedef struct arena_s arena_t;
|
typedef struct arena_s arena_t;
|
||||||
typedef struct arena_tdata_s arena_tdata_t;
|
typedef struct arena_tdata_s arena_tdata_t;
|
||||||
@@ -189,6 +190,14 @@ struct arena_chunk_s {
|
|||||||
*/
|
*/
|
||||||
extent_node_t node;
|
extent_node_t node;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* True if memory could be backed by transparent huge pages. This is
|
||||||
|
* only directly relevant to Linux, since it is the only supported
|
||||||
|
* platform on which jemalloc interacts with explicit transparent huge
|
||||||
|
* page controls.
|
||||||
|
*/
|
||||||
|
bool hugepage;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map of pages within chunk that keeps track of free/large/small. The
|
* Map of pages within chunk that keeps track of free/large/small. The
|
||||||
* first map_bias entries are omitted, since the chunk header does not
|
* first map_bias entries are omitted, since the chunk header does not
|
||||||
@@ -257,6 +266,49 @@ struct arena_bin_info_s {
|
|||||||
uint32_t reg0_offset;
|
uint32_t reg0_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct arena_decay_s {
|
||||||
|
/*
|
||||||
|
* Approximate time in seconds from the creation of a set of unused
|
||||||
|
* dirty pages until an equivalent set of unused dirty pages is purged
|
||||||
|
* and/or reused.
|
||||||
|
*/
|
||||||
|
ssize_t time;
|
||||||
|
/* time / SMOOTHSTEP_NSTEPS. */
|
||||||
|
nstime_t interval;
|
||||||
|
/*
|
||||||
|
* Time at which the current decay interval logically started. We do
|
||||||
|
* not actually advance to a new epoch until sometime after it starts
|
||||||
|
* because of scheduling and computation delays, and it is even possible
|
||||||
|
* to completely skip epochs. In all cases, during epoch advancement we
|
||||||
|
* merge all relevant activity into the most recently recorded epoch.
|
||||||
|
*/
|
||||||
|
nstime_t epoch;
|
||||||
|
/* Deadline randomness generator. */
|
||||||
|
uint64_t jitter_state;
|
||||||
|
/*
|
||||||
|
* Deadline for current epoch. This is the sum of interval and per
|
||||||
|
* epoch jitter which is a uniform random variable in [0..interval).
|
||||||
|
* Epochs always advance by precise multiples of interval, but we
|
||||||
|
* randomize the deadline to reduce the likelihood of arenas purging in
|
||||||
|
* lockstep.
|
||||||
|
*/
|
||||||
|
nstime_t deadline;
|
||||||
|
/*
|
||||||
|
* Number of dirty pages at beginning of current epoch. During epoch
|
||||||
|
* advancement we use the delta between arena->decay.ndirty and
|
||||||
|
* arena->ndirty to determine how many dirty pages, if any, were
|
||||||
|
* generated.
|
||||||
|
*/
|
||||||
|
size_t ndirty;
|
||||||
|
/*
|
||||||
|
* Trailing log of how many unused dirty pages were generated during
|
||||||
|
* each of the past SMOOTHSTEP_NSTEPS decay epochs, where the last
|
||||||
|
* element is the most recent epoch. Corresponding epoch times are
|
||||||
|
* relative to epoch.
|
||||||
|
*/
|
||||||
|
size_t backlog[SMOOTHSTEP_NSTEPS];
|
||||||
|
};
|
||||||
|
|
||||||
struct arena_bin_s {
|
struct arena_bin_s {
|
||||||
/*
|
/*
|
||||||
* All operations on runcur, runs, and stats require that lock be
|
* All operations on runcur, runs, and stats require that lock be
|
||||||
@@ -326,14 +378,16 @@ struct arena_s {
|
|||||||
* PRNG state for cache index randomization of large allocation base
|
* PRNG state for cache index randomization of large allocation base
|
||||||
* pointers.
|
* pointers.
|
||||||
*/
|
*/
|
||||||
uint64_t offset_state;
|
size_t offset_state;
|
||||||
|
|
||||||
dss_prec_t dss_prec;
|
dss_prec_t dss_prec;
|
||||||
|
|
||||||
|
|
||||||
/* Extant arena chunks. */
|
/* Extant arena chunks. */
|
||||||
ql_head(extent_node_t) achunks;
|
ql_head(extent_node_t) achunks;
|
||||||
|
|
||||||
|
/* Extent serial number generator state. */
|
||||||
|
size_t extent_sn_next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In order to avoid rapid chunk allocation/deallocation when an arena
|
* In order to avoid rapid chunk allocation/deallocation when an arena
|
||||||
* oscillates right on the cusp of needing a new chunk, cache the most
|
* oscillates right on the cusp of needing a new chunk, cache the most
|
||||||
@@ -394,52 +448,8 @@ struct arena_s {
|
|||||||
arena_runs_dirty_link_t runs_dirty;
|
arena_runs_dirty_link_t runs_dirty;
|
||||||
extent_node_t chunks_cache;
|
extent_node_t chunks_cache;
|
||||||
|
|
||||||
/*
|
/* Decay-based purging state. */
|
||||||
* Approximate time in seconds from the creation of a set of unused
|
arena_decay_t decay;
|
||||||
* dirty pages until an equivalent set of unused dirty pages is purged
|
|
||||||
* and/or reused.
|
|
||||||
*/
|
|
||||||
ssize_t decay_time;
|
|
||||||
/* decay_time / SMOOTHSTEP_NSTEPS. */
|
|
||||||
nstime_t decay_interval;
|
|
||||||
/*
|
|
||||||
* Time at which the current decay interval logically started. We do
|
|
||||||
* not actually advance to a new epoch until sometime after it starts
|
|
||||||
* because of scheduling and computation delays, and it is even possible
|
|
||||||
* to completely skip epochs. In all cases, during epoch advancement we
|
|
||||||
* merge all relevant activity into the most recently recorded epoch.
|
|
||||||
*/
|
|
||||||
nstime_t decay_epoch;
|
|
||||||
/* decay_deadline randomness generator. */
|
|
||||||
uint64_t decay_jitter_state;
|
|
||||||
/*
|
|
||||||
* Deadline for current epoch. This is the sum of decay_interval and
|
|
||||||
* per epoch jitter which is a uniform random variable in
|
|
||||||
* [0..decay_interval). Epochs always advance by precise multiples of
|
|
||||||
* decay_interval, but we randomize the deadline to reduce the
|
|
||||||
* likelihood of arenas purging in lockstep.
|
|
||||||
*/
|
|
||||||
nstime_t decay_deadline;
|
|
||||||
/*
|
|
||||||
* Number of dirty pages at beginning of current epoch. During epoch
|
|
||||||
* advancement we use the delta between decay_ndirty and ndirty to
|
|
||||||
* determine how many dirty pages, if any, were generated, and record
|
|
||||||
* the result in decay_backlog.
|
|
||||||
*/
|
|
||||||
size_t decay_ndirty;
|
|
||||||
/*
|
|
||||||
* Memoized result of arena_decay_backlog_npages_limit() corresponding
|
|
||||||
* to the current contents of decay_backlog, i.e. the limit on how many
|
|
||||||
* pages are allowed to exist for the decay epochs.
|
|
||||||
*/
|
|
||||||
size_t decay_backlog_npages_limit;
|
|
||||||
/*
|
|
||||||
* Trailing log of how many unused dirty pages were generated during
|
|
||||||
* each of the past SMOOTHSTEP_NSTEPS decay epochs, where the last
|
|
||||||
* element is the most recent epoch. Corresponding epoch times are
|
|
||||||
* relative to decay_epoch.
|
|
||||||
*/
|
|
||||||
size_t decay_backlog[SMOOTHSTEP_NSTEPS];
|
|
||||||
|
|
||||||
/* Extant huge allocations. */
|
/* Extant huge allocations. */
|
||||||
ql_head(extent_node_t) huge;
|
ql_head(extent_node_t) huge;
|
||||||
@@ -453,9 +463,9 @@ struct arena_s {
|
|||||||
* orderings are needed, which is why there are two trees with the same
|
* orderings are needed, which is why there are two trees with the same
|
||||||
* contents.
|
* contents.
|
||||||
*/
|
*/
|
||||||
extent_tree_t chunks_szad_cached;
|
extent_tree_t chunks_szsnad_cached;
|
||||||
extent_tree_t chunks_ad_cached;
|
extent_tree_t chunks_ad_cached;
|
||||||
extent_tree_t chunks_szad_retained;
|
extent_tree_t chunks_szsnad_retained;
|
||||||
extent_tree_t chunks_ad_retained;
|
extent_tree_t chunks_ad_retained;
|
||||||
|
|
||||||
malloc_mutex_t chunks_mtx;
|
malloc_mutex_t chunks_mtx;
|
||||||
@@ -470,10 +480,12 @@ struct arena_s {
|
|||||||
arena_bin_t bins[NBINS];
|
arena_bin_t bins[NBINS];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Quantized address-ordered heaps of this arena's available runs. The
|
* Size-segregated address-ordered heaps of this arena's available runs,
|
||||||
* heaps are used for first-best-fit run allocation.
|
* used for first-best-fit run allocation. Runs are quantized, i.e.
|
||||||
|
* they reside in the last heap which corresponds to a size class less
|
||||||
|
* than or equal to the run size.
|
||||||
*/
|
*/
|
||||||
arena_run_heap_t runs_avail[1]; /* Dynamically sized. */
|
arena_run_heap_t runs_avail[NPSIZES];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Used in conjunction with tsd for fast arena-related context lookup. */
|
/* Used in conjunction with tsd for fast arena-related context lookup. */
|
||||||
@@ -505,7 +517,6 @@ extern size_t map_bias; /* Number of arena chunk header pages. */
|
|||||||
extern size_t map_misc_offset;
|
extern size_t map_misc_offset;
|
||||||
extern size_t arena_maxrun; /* Max run size for arenas. */
|
extern size_t arena_maxrun; /* Max run size for arenas. */
|
||||||
extern size_t large_maxclass; /* Max large size class. */
|
extern size_t large_maxclass; /* Max large size class. */
|
||||||
extern size_t run_quantize_max; /* Max run_quantize_*() input. */
|
|
||||||
extern unsigned nlclasses; /* Number of large size classes. */
|
extern unsigned nlclasses; /* Number of large size classes. */
|
||||||
extern unsigned nhclasses; /* Number of huge size classes. */
|
extern unsigned nhclasses; /* Number of huge size classes. */
|
||||||
|
|
||||||
@@ -521,13 +532,13 @@ void arena_chunk_cache_maybe_remove(arena_t *arena, extent_node_t *node,
|
|||||||
extent_node_t *arena_node_alloc(tsdn_t *tsdn, arena_t *arena);
|
extent_node_t *arena_node_alloc(tsdn_t *tsdn, arena_t *arena);
|
||||||
void arena_node_dalloc(tsdn_t *tsdn, arena_t *arena, extent_node_t *node);
|
void arena_node_dalloc(tsdn_t *tsdn, arena_t *arena, extent_node_t *node);
|
||||||
void *arena_chunk_alloc_huge(tsdn_t *tsdn, arena_t *arena, size_t usize,
|
void *arena_chunk_alloc_huge(tsdn_t *tsdn, arena_t *arena, size_t usize,
|
||||||
size_t alignment, bool *zero);
|
size_t alignment, size_t *sn, bool *zero);
|
||||||
void arena_chunk_dalloc_huge(tsdn_t *tsdn, arena_t *arena, void *chunk,
|
void arena_chunk_dalloc_huge(tsdn_t *tsdn, arena_t *arena, void *chunk,
|
||||||
size_t usize);
|
size_t usize, size_t sn);
|
||||||
void arena_chunk_ralloc_huge_similar(tsdn_t *tsdn, arena_t *arena,
|
void arena_chunk_ralloc_huge_similar(tsdn_t *tsdn, arena_t *arena,
|
||||||
void *chunk, size_t oldsize, size_t usize);
|
void *chunk, size_t oldsize, size_t usize);
|
||||||
void arena_chunk_ralloc_huge_shrink(tsdn_t *tsdn, arena_t *arena,
|
void arena_chunk_ralloc_huge_shrink(tsdn_t *tsdn, arena_t *arena,
|
||||||
void *chunk, size_t oldsize, size_t usize);
|
void *chunk, size_t oldsize, size_t usize, size_t sn);
|
||||||
bool arena_chunk_ralloc_huge_expand(tsdn_t *tsdn, arena_t *arena,
|
bool arena_chunk_ralloc_huge_expand(tsdn_t *tsdn, arena_t *arena,
|
||||||
void *chunk, size_t oldsize, size_t usize, bool *zero);
|
void *chunk, size_t oldsize, size_t usize, bool *zero);
|
||||||
ssize_t arena_lg_dirty_mult_get(tsdn_t *tsdn, arena_t *arena);
|
ssize_t arena_lg_dirty_mult_get(tsdn_t *tsdn, arena_t *arena);
|
||||||
@@ -600,8 +611,9 @@ void arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
|
|||||||
unsigned arena_nthreads_get(arena_t *arena, bool internal);
|
unsigned arena_nthreads_get(arena_t *arena, bool internal);
|
||||||
void arena_nthreads_inc(arena_t *arena, bool internal);
|
void arena_nthreads_inc(arena_t *arena, bool internal);
|
||||||
void arena_nthreads_dec(arena_t *arena, bool internal);
|
void arena_nthreads_dec(arena_t *arena, bool internal);
|
||||||
|
size_t arena_extent_sn_next(arena_t *arena);
|
||||||
arena_t *arena_new(tsdn_t *tsdn, unsigned ind);
|
arena_t *arena_new(tsdn_t *tsdn, unsigned ind);
|
||||||
bool arena_boot(void);
|
void arena_boot(void);
|
||||||
void arena_prefork0(tsdn_t *tsdn, arena_t *arena);
|
void arena_prefork0(tsdn_t *tsdn, arena_t *arena);
|
||||||
void arena_prefork1(tsdn_t *tsdn, arena_t *arena);
|
void arena_prefork1(tsdn_t *tsdn, arena_t *arena);
|
||||||
void arena_prefork2(tsdn_t *tsdn, arena_t *arena);
|
void arena_prefork2(tsdn_t *tsdn, arena_t *arena);
|
||||||
|
|||||||
@@ -58,22 +58,20 @@ void chunk_deregister(const void *chunk, const extent_node_t *node);
|
|||||||
void *chunk_alloc_base(size_t size);
|
void *chunk_alloc_base(size_t size);
|
||||||
void *chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena,
|
void *chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena,
|
||||||
chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,
|
chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,
|
||||||
bool *zero, bool dalloc_node);
|
size_t *sn, bool *zero, bool *commit, bool dalloc_node);
|
||||||
void *chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena,
|
void *chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena,
|
||||||
chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,
|
chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,
|
||||||
bool *zero, bool *commit);
|
size_t *sn, bool *zero, bool *commit);
|
||||||
void chunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena,
|
void chunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena,
|
||||||
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, bool committed);
|
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, size_t sn,
|
||||||
void chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena,
|
|
||||||
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, bool zeroed,
|
|
||||||
bool committed);
|
bool committed);
|
||||||
|
void chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena,
|
||||||
|
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, size_t sn,
|
||||||
|
bool zeroed, bool committed);
|
||||||
bool chunk_purge_wrapper(tsdn_t *tsdn, arena_t *arena,
|
bool chunk_purge_wrapper(tsdn_t *tsdn, arena_t *arena,
|
||||||
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, size_t offset,
|
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, size_t offset,
|
||||||
size_t length);
|
size_t length);
|
||||||
bool chunk_boot(void);
|
bool chunk_boot(void);
|
||||||
void chunk_prefork(tsdn_t *tsdn);
|
|
||||||
void chunk_postfork_parent(tsdn_t *tsdn);
|
|
||||||
void chunk_postfork_child(tsdn_t *tsdn);
|
|
||||||
|
|
||||||
#endif /* JEMALLOC_H_EXTERNS */
|
#endif /* JEMALLOC_H_EXTERNS */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|||||||
@@ -21,15 +21,13 @@ extern const char *dss_prec_names[];
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
#ifdef JEMALLOC_H_EXTERNS
|
#ifdef JEMALLOC_H_EXTERNS
|
||||||
|
|
||||||
dss_prec_t chunk_dss_prec_get(tsdn_t *tsdn);
|
dss_prec_t chunk_dss_prec_get(void);
|
||||||
bool chunk_dss_prec_set(tsdn_t *tsdn, dss_prec_t dss_prec);
|
bool chunk_dss_prec_set(dss_prec_t dss_prec);
|
||||||
void *chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr,
|
void *chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr,
|
||||||
size_t size, size_t alignment, bool *zero, bool *commit);
|
size_t size, size_t alignment, bool *zero, bool *commit);
|
||||||
bool chunk_in_dss(tsdn_t *tsdn, void *chunk);
|
bool chunk_in_dss(void *chunk);
|
||||||
bool chunk_dss_boot(void);
|
bool chunk_dss_mergeable(void *chunk_a, void *chunk_b);
|
||||||
void chunk_dss_prefork(tsdn_t *tsdn);
|
void chunk_dss_boot(void);
|
||||||
void chunk_dss_postfork_parent(tsdn_t *tsdn);
|
|
||||||
void chunk_dss_postfork_child(tsdn_t *tsdn);
|
|
||||||
|
|
||||||
#endif /* JEMALLOC_H_EXTERNS */
|
#endif /* JEMALLOC_H_EXTERNS */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|||||||
@@ -64,13 +64,13 @@ struct ckh_s {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
#ifdef JEMALLOC_H_EXTERNS
|
#ifdef JEMALLOC_H_EXTERNS
|
||||||
|
|
||||||
bool ckh_new(tsdn_t *tsdn, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
|
bool ckh_new(tsd_t *tsd, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
|
||||||
ckh_keycomp_t *keycomp);
|
ckh_keycomp_t *keycomp);
|
||||||
void ckh_delete(tsdn_t *tsdn, ckh_t *ckh);
|
void ckh_delete(tsd_t *tsd, ckh_t *ckh);
|
||||||
size_t ckh_count(ckh_t *ckh);
|
size_t ckh_count(ckh_t *ckh);
|
||||||
bool ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data);
|
bool ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data);
|
||||||
bool ckh_insert(tsdn_t *tsdn, ckh_t *ckh, const void *key, const void *data);
|
bool ckh_insert(tsd_t *tsd, ckh_t *ckh, const void *key, const void *data);
|
||||||
bool ckh_remove(tsdn_t *tsdn, ckh_t *ckh, const void *searchkey, void **key,
|
bool ckh_remove(tsd_t *tsd, ckh_t *ckh, const void *searchkey, void **key,
|
||||||
void **data);
|
void **data);
|
||||||
bool ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data);
|
bool ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data);
|
||||||
void ckh_string_hash(const void *key, size_t r_hash[2]);
|
void ckh_string_hash(const void *key, size_t r_hash[2]);
|
||||||
|
|||||||
@@ -18,6 +18,20 @@ struct extent_node_s {
|
|||||||
/* Total region size. */
|
/* Total region size. */
|
||||||
size_t en_size;
|
size_t en_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Serial number (potentially non-unique).
|
||||||
|
*
|
||||||
|
* In principle serial numbers can wrap around on 32-bit systems if
|
||||||
|
* JEMALLOC_MUNMAP is defined, but as long as comparison functions fall
|
||||||
|
* back on address comparison for equal serial numbers, stable (if
|
||||||
|
* imperfect) ordering is maintained.
|
||||||
|
*
|
||||||
|
* Serial numbers may not be unique even in the absence of wrap-around,
|
||||||
|
* e.g. when splitting an extent and assigning the same serial number to
|
||||||
|
* both resulting adjacent extents.
|
||||||
|
*/
|
||||||
|
size_t en_sn;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The zeroed flag is used by chunk recycling code to track whether
|
* The zeroed flag is used by chunk recycling code to track whether
|
||||||
* memory is zero-filled.
|
* memory is zero-filled.
|
||||||
@@ -45,8 +59,8 @@ struct extent_node_s {
|
|||||||
qr(extent_node_t) cc_link;
|
qr(extent_node_t) cc_link;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
/* Linkage for the size/address-ordered tree. */
|
/* Linkage for the size/sn/address-ordered tree. */
|
||||||
rb_node(extent_node_t) szad_link;
|
rb_node(extent_node_t) szsnad_link;
|
||||||
|
|
||||||
/* Linkage for arena's achunks, huge, and node_cache lists. */
|
/* Linkage for arena's achunks, huge, and node_cache lists. */
|
||||||
ql_elm(extent_node_t) ql_link;
|
ql_elm(extent_node_t) ql_link;
|
||||||
@@ -61,7 +75,7 @@ typedef rb_tree(extent_node_t) extent_tree_t;
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
#ifdef JEMALLOC_H_EXTERNS
|
#ifdef JEMALLOC_H_EXTERNS
|
||||||
|
|
||||||
rb_proto(, extent_tree_szad_, extent_tree_t, extent_node_t)
|
rb_proto(, extent_tree_szsnad_, extent_tree_t, extent_node_t)
|
||||||
|
|
||||||
rb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)
|
rb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)
|
||||||
|
|
||||||
@@ -73,6 +87,7 @@ rb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)
|
|||||||
arena_t *extent_node_arena_get(const extent_node_t *node);
|
arena_t *extent_node_arena_get(const extent_node_t *node);
|
||||||
void *extent_node_addr_get(const extent_node_t *node);
|
void *extent_node_addr_get(const extent_node_t *node);
|
||||||
size_t extent_node_size_get(const extent_node_t *node);
|
size_t extent_node_size_get(const extent_node_t *node);
|
||||||
|
size_t extent_node_sn_get(const extent_node_t *node);
|
||||||
bool extent_node_zeroed_get(const extent_node_t *node);
|
bool extent_node_zeroed_get(const extent_node_t *node);
|
||||||
bool extent_node_committed_get(const extent_node_t *node);
|
bool extent_node_committed_get(const extent_node_t *node);
|
||||||
bool extent_node_achunk_get(const extent_node_t *node);
|
bool extent_node_achunk_get(const extent_node_t *node);
|
||||||
@@ -80,12 +95,13 @@ prof_tctx_t *extent_node_prof_tctx_get(const extent_node_t *node);
|
|||||||
void extent_node_arena_set(extent_node_t *node, arena_t *arena);
|
void extent_node_arena_set(extent_node_t *node, arena_t *arena);
|
||||||
void extent_node_addr_set(extent_node_t *node, void *addr);
|
void extent_node_addr_set(extent_node_t *node, void *addr);
|
||||||
void extent_node_size_set(extent_node_t *node, size_t size);
|
void extent_node_size_set(extent_node_t *node, size_t size);
|
||||||
|
void extent_node_sn_set(extent_node_t *node, size_t sn);
|
||||||
void extent_node_zeroed_set(extent_node_t *node, bool zeroed);
|
void extent_node_zeroed_set(extent_node_t *node, bool zeroed);
|
||||||
void extent_node_committed_set(extent_node_t *node, bool committed);
|
void extent_node_committed_set(extent_node_t *node, bool committed);
|
||||||
void extent_node_achunk_set(extent_node_t *node, bool achunk);
|
void extent_node_achunk_set(extent_node_t *node, bool achunk);
|
||||||
void extent_node_prof_tctx_set(extent_node_t *node, prof_tctx_t *tctx);
|
void extent_node_prof_tctx_set(extent_node_t *node, prof_tctx_t *tctx);
|
||||||
void extent_node_init(extent_node_t *node, arena_t *arena, void *addr,
|
void extent_node_init(extent_node_t *node, arena_t *arena, void *addr,
|
||||||
size_t size, bool zeroed, bool committed);
|
size_t size, size_t sn, bool zeroed, bool committed);
|
||||||
void extent_node_dirty_linkage_init(extent_node_t *node);
|
void extent_node_dirty_linkage_init(extent_node_t *node);
|
||||||
void extent_node_dirty_insert(extent_node_t *node,
|
void extent_node_dirty_insert(extent_node_t *node,
|
||||||
arena_runs_dirty_link_t *runs_dirty, extent_node_t *chunks_dirty);
|
arena_runs_dirty_link_t *runs_dirty, extent_node_t *chunks_dirty);
|
||||||
@@ -114,6 +130,13 @@ extent_node_size_get(const extent_node_t *node)
|
|||||||
return (node->en_size);
|
return (node->en_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE size_t
|
||||||
|
extent_node_sn_get(const extent_node_t *node)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (node->en_sn);
|
||||||
|
}
|
||||||
|
|
||||||
JEMALLOC_INLINE bool
|
JEMALLOC_INLINE bool
|
||||||
extent_node_zeroed_get(const extent_node_t *node)
|
extent_node_zeroed_get(const extent_node_t *node)
|
||||||
{
|
{
|
||||||
@@ -164,6 +187,13 @@ extent_node_size_set(extent_node_t *node, size_t size)
|
|||||||
node->en_size = size;
|
node->en_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
extent_node_sn_set(extent_node_t *node, size_t sn)
|
||||||
|
{
|
||||||
|
|
||||||
|
node->en_sn = sn;
|
||||||
|
}
|
||||||
|
|
||||||
JEMALLOC_INLINE void
|
JEMALLOC_INLINE void
|
||||||
extent_node_zeroed_set(extent_node_t *node, bool zeroed)
|
extent_node_zeroed_set(extent_node_t *node, bool zeroed)
|
||||||
{
|
{
|
||||||
@@ -194,12 +224,13 @@ extent_node_prof_tctx_set(extent_node_t *node, prof_tctx_t *tctx)
|
|||||||
|
|
||||||
JEMALLOC_INLINE void
|
JEMALLOC_INLINE void
|
||||||
extent_node_init(extent_node_t *node, arena_t *arena, void *addr, size_t size,
|
extent_node_init(extent_node_t *node, arena_t *arena, void *addr, size_t size,
|
||||||
bool zeroed, bool committed)
|
size_t sn, bool zeroed, bool committed)
|
||||||
{
|
{
|
||||||
|
|
||||||
extent_node_arena_set(node, arena);
|
extent_node_arena_set(node, arena);
|
||||||
extent_node_addr_set(node, addr);
|
extent_node_addr_set(node, addr);
|
||||||
extent_node_size_set(node, size);
|
extent_node_size_set(node, size);
|
||||||
|
extent_node_sn_set(node, sn);
|
||||||
extent_node_zeroed_set(node, zeroed);
|
extent_node_zeroed_set(node, zeroed);
|
||||||
extent_node_committed_set(node, committed);
|
extent_node_committed_set(node, committed);
|
||||||
extent_node_achunk_set(node, false);
|
extent_node_achunk_set(node, false);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ bool huge_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize,
|
|||||||
void *huge_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize,
|
void *huge_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize,
|
||||||
size_t usize, size_t alignment, bool zero, tcache_t *tcache);
|
size_t usize, size_t alignment, bool zero, tcache_t *tcache);
|
||||||
#ifdef JEMALLOC_JET
|
#ifdef JEMALLOC_JET
|
||||||
typedef void (huge_dalloc_junk_t)(tsdn_t *, void *, size_t);
|
typedef void (huge_dalloc_junk_t)(void *, size_t);
|
||||||
extern huge_dalloc_junk_t *huge_dalloc_junk;
|
extern huge_dalloc_junk_t *huge_dalloc_junk;
|
||||||
#endif
|
#endif
|
||||||
void huge_dalloc(tsdn_t *tsdn, void *ptr);
|
void huge_dalloc(tsdn_t *tsdn, void *ptr);
|
||||||
|
|||||||
@@ -162,7 +162,9 @@ static const bool config_cache_oblivious =
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "jemalloc/internal/ph.h"
|
#include "jemalloc/internal/ph.h"
|
||||||
|
#ifndef __PGI
|
||||||
#define RB_COMPACT
|
#define RB_COMPACT
|
||||||
|
#endif
|
||||||
#include "jemalloc/internal/rb.h"
|
#include "jemalloc/internal/rb.h"
|
||||||
#include "jemalloc/internal/qr.h"
|
#include "jemalloc/internal/qr.h"
|
||||||
#include "jemalloc/internal/ql.h"
|
#include "jemalloc/internal/ql.h"
|
||||||
@@ -185,6 +187,9 @@ static const bool config_cache_oblivious =
|
|||||||
|
|
||||||
#include "jemalloc/internal/jemalloc_internal_macros.h"
|
#include "jemalloc/internal/jemalloc_internal_macros.h"
|
||||||
|
|
||||||
|
/* Page size index type. */
|
||||||
|
typedef unsigned pszind_t;
|
||||||
|
|
||||||
/* Size class index type. */
|
/* Size class index type. */
|
||||||
typedef unsigned szind_t;
|
typedef unsigned szind_t;
|
||||||
|
|
||||||
@@ -234,7 +239,7 @@ typedef unsigned szind_t;
|
|||||||
# ifdef __alpha__
|
# ifdef __alpha__
|
||||||
# define LG_QUANTUM 4
|
# define LG_QUANTUM 4
|
||||||
# endif
|
# endif
|
||||||
# if (defined(__sparc64__) || defined(__sparcv9))
|
# if (defined(__sparc64__) || defined(__sparcv9) || defined(__sparc_v9__))
|
||||||
# define LG_QUANTUM 4
|
# define LG_QUANTUM 4
|
||||||
# endif
|
# endif
|
||||||
# if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64))
|
# if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64))
|
||||||
@@ -332,7 +337,7 @@ typedef unsigned szind_t;
|
|||||||
|
|
||||||
/* Return the nearest aligned address at or below a. */
|
/* Return the nearest aligned address at or below a. */
|
||||||
#define ALIGNMENT_ADDR2BASE(a, alignment) \
|
#define ALIGNMENT_ADDR2BASE(a, alignment) \
|
||||||
((void *)((uintptr_t)(a) & (-(alignment))))
|
((void *)((uintptr_t)(a) & ((~(alignment)) + 1)))
|
||||||
|
|
||||||
/* Return the offset between a and the nearest aligned address at or below a. */
|
/* Return the offset between a and the nearest aligned address at or below a. */
|
||||||
#define ALIGNMENT_ADDR2OFFSET(a, alignment) \
|
#define ALIGNMENT_ADDR2OFFSET(a, alignment) \
|
||||||
@@ -340,7 +345,7 @@ typedef unsigned szind_t;
|
|||||||
|
|
||||||
/* Return the smallest alignment multiple that is >= s. */
|
/* Return the smallest alignment multiple that is >= s. */
|
||||||
#define ALIGNMENT_CEILING(s, alignment) \
|
#define ALIGNMENT_CEILING(s, alignment) \
|
||||||
(((s) + (alignment - 1)) & (-(alignment)))
|
(((s) + (alignment - 1)) & ((~(alignment)) + 1))
|
||||||
|
|
||||||
/* Declare a variable-length array. */
|
/* Declare a variable-length array. */
|
||||||
#if __STDC_VERSION__ < 199901L
|
#if __STDC_VERSION__ < 199901L
|
||||||
@@ -364,6 +369,7 @@ typedef unsigned szind_t;
|
|||||||
#include "jemalloc/internal/valgrind.h"
|
#include "jemalloc/internal/valgrind.h"
|
||||||
#include "jemalloc/internal/util.h"
|
#include "jemalloc/internal/util.h"
|
||||||
#include "jemalloc/internal/atomic.h"
|
#include "jemalloc/internal/atomic.h"
|
||||||
|
#include "jemalloc/internal/spin.h"
|
||||||
#include "jemalloc/internal/prng.h"
|
#include "jemalloc/internal/prng.h"
|
||||||
#include "jemalloc/internal/ticker.h"
|
#include "jemalloc/internal/ticker.h"
|
||||||
#include "jemalloc/internal/ckh.h"
|
#include "jemalloc/internal/ckh.h"
|
||||||
@@ -396,6 +402,7 @@ typedef unsigned szind_t;
|
|||||||
#include "jemalloc/internal/valgrind.h"
|
#include "jemalloc/internal/valgrind.h"
|
||||||
#include "jemalloc/internal/util.h"
|
#include "jemalloc/internal/util.h"
|
||||||
#include "jemalloc/internal/atomic.h"
|
#include "jemalloc/internal/atomic.h"
|
||||||
|
#include "jemalloc/internal/spin.h"
|
||||||
#include "jemalloc/internal/prng.h"
|
#include "jemalloc/internal/prng.h"
|
||||||
#include "jemalloc/internal/ticker.h"
|
#include "jemalloc/internal/ticker.h"
|
||||||
#include "jemalloc/internal/ckh.h"
|
#include "jemalloc/internal/ckh.h"
|
||||||
@@ -455,11 +462,16 @@ extern unsigned narenas_auto;
|
|||||||
*/
|
*/
|
||||||
extern arena_t **arenas;
|
extern arena_t **arenas;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pind2sz_tab encodes the same information as could be computed by
|
||||||
|
* pind2sz_compute().
|
||||||
|
*/
|
||||||
|
extern size_t const pind2sz_tab[NPSIZES];
|
||||||
/*
|
/*
|
||||||
* index2size_tab encodes the same information as could be computed (at
|
* index2size_tab encodes the same information as could be computed (at
|
||||||
* unacceptable cost in some code paths) by index2size_compute().
|
* unacceptable cost in some code paths) by index2size_compute().
|
||||||
*/
|
*/
|
||||||
extern size_t const index2size_tab[NSIZES+1];
|
extern size_t const index2size_tab[NSIZES];
|
||||||
/*
|
/*
|
||||||
* size2index_tab is a compact lookup table that rounds request sizes up to
|
* size2index_tab is a compact lookup table that rounds request sizes up to
|
||||||
* size classes. In order to reduce cache footprint, the table is compressed,
|
* size classes. In order to reduce cache footprint, the table is compressed,
|
||||||
@@ -467,6 +479,7 @@ extern size_t const index2size_tab[NSIZES+1];
|
|||||||
*/
|
*/
|
||||||
extern uint8_t const size2index_tab[];
|
extern uint8_t const size2index_tab[];
|
||||||
|
|
||||||
|
arena_t *a0get(void);
|
||||||
void *a0malloc(size_t size);
|
void *a0malloc(size_t size);
|
||||||
void a0dalloc(void *ptr);
|
void a0dalloc(void *ptr);
|
||||||
void *bootstrap_malloc(size_t size);
|
void *bootstrap_malloc(size_t size);
|
||||||
@@ -492,6 +505,7 @@ void jemalloc_postfork_child(void);
|
|||||||
#include "jemalloc/internal/valgrind.h"
|
#include "jemalloc/internal/valgrind.h"
|
||||||
#include "jemalloc/internal/util.h"
|
#include "jemalloc/internal/util.h"
|
||||||
#include "jemalloc/internal/atomic.h"
|
#include "jemalloc/internal/atomic.h"
|
||||||
|
#include "jemalloc/internal/spin.h"
|
||||||
#include "jemalloc/internal/prng.h"
|
#include "jemalloc/internal/prng.h"
|
||||||
#include "jemalloc/internal/ticker.h"
|
#include "jemalloc/internal/ticker.h"
|
||||||
#include "jemalloc/internal/ckh.h"
|
#include "jemalloc/internal/ckh.h"
|
||||||
@@ -524,6 +538,7 @@ void jemalloc_postfork_child(void);
|
|||||||
#include "jemalloc/internal/valgrind.h"
|
#include "jemalloc/internal/valgrind.h"
|
||||||
#include "jemalloc/internal/util.h"
|
#include "jemalloc/internal/util.h"
|
||||||
#include "jemalloc/internal/atomic.h"
|
#include "jemalloc/internal/atomic.h"
|
||||||
|
#include "jemalloc/internal/spin.h"
|
||||||
#include "jemalloc/internal/prng.h"
|
#include "jemalloc/internal/prng.h"
|
||||||
#include "jemalloc/internal/ticker.h"
|
#include "jemalloc/internal/ticker.h"
|
||||||
#include "jemalloc/internal/ckh.h"
|
#include "jemalloc/internal/ckh.h"
|
||||||
@@ -543,6 +558,11 @@ void jemalloc_postfork_child(void);
|
|||||||
#include "jemalloc/internal/huge.h"
|
#include "jemalloc/internal/huge.h"
|
||||||
|
|
||||||
#ifndef JEMALLOC_ENABLE_INLINE
|
#ifndef JEMALLOC_ENABLE_INLINE
|
||||||
|
pszind_t psz2ind(size_t psz);
|
||||||
|
size_t pind2sz_compute(pszind_t pind);
|
||||||
|
size_t pind2sz_lookup(pszind_t pind);
|
||||||
|
size_t pind2sz(pszind_t pind);
|
||||||
|
size_t psz2u(size_t psz);
|
||||||
szind_t size2index_compute(size_t size);
|
szind_t size2index_compute(size_t size);
|
||||||
szind_t size2index_lookup(size_t size);
|
szind_t size2index_lookup(size_t size);
|
||||||
szind_t size2index(size_t size);
|
szind_t size2index(size_t size);
|
||||||
@@ -555,7 +575,7 @@ size_t s2u(size_t size);
|
|||||||
size_t sa2u(size_t size, size_t alignment);
|
size_t sa2u(size_t size, size_t alignment);
|
||||||
arena_t *arena_choose_impl(tsd_t *tsd, arena_t *arena, bool internal);
|
arena_t *arena_choose_impl(tsd_t *tsd, arena_t *arena, bool internal);
|
||||||
arena_t *arena_choose(tsd_t *tsd, arena_t *arena);
|
arena_t *arena_choose(tsd_t *tsd, arena_t *arena);
|
||||||
arena_t *arena_ichoose(tsdn_t *tsdn, arena_t *arena);
|
arena_t *arena_ichoose(tsd_t *tsd, arena_t *arena);
|
||||||
arena_tdata_t *arena_tdata_get(tsd_t *tsd, unsigned ind,
|
arena_tdata_t *arena_tdata_get(tsd_t *tsd, unsigned ind,
|
||||||
bool refresh_if_missing);
|
bool refresh_if_missing);
|
||||||
arena_t *arena_get(tsdn_t *tsdn, unsigned ind, bool init_if_missing);
|
arena_t *arena_get(tsdn_t *tsdn, unsigned ind, bool init_if_missing);
|
||||||
@@ -563,10 +583,90 @@ ticker_t *decay_ticker_get(tsd_t *tsd, unsigned ind);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
|
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
|
||||||
|
JEMALLOC_INLINE pszind_t
|
||||||
|
psz2ind(size_t psz)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (unlikely(psz > HUGE_MAXCLASS))
|
||||||
|
return (NPSIZES);
|
||||||
|
{
|
||||||
|
pszind_t x = lg_floor((psz<<1)-1);
|
||||||
|
pszind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_PAGE) ? 0 : x -
|
||||||
|
(LG_SIZE_CLASS_GROUP + LG_PAGE);
|
||||||
|
pszind_t grp = shift << LG_SIZE_CLASS_GROUP;
|
||||||
|
|
||||||
|
pszind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ?
|
||||||
|
LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1;
|
||||||
|
|
||||||
|
size_t delta_inverse_mask = ZI(-1) << lg_delta;
|
||||||
|
pszind_t mod = ((((psz-1) & delta_inverse_mask) >> lg_delta)) &
|
||||||
|
((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
|
||||||
|
|
||||||
|
pszind_t ind = grp + mod;
|
||||||
|
return (ind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE size_t
|
||||||
|
pind2sz_compute(pszind_t pind)
|
||||||
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t grp = pind >> LG_SIZE_CLASS_GROUP;
|
||||||
|
size_t mod = pind & ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
|
||||||
|
|
||||||
|
size_t grp_size_mask = ~((!!grp)-1);
|
||||||
|
size_t grp_size = ((ZU(1) << (LG_PAGE +
|
||||||
|
(LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask;
|
||||||
|
|
||||||
|
size_t shift = (grp == 0) ? 1 : grp;
|
||||||
|
size_t lg_delta = shift + (LG_PAGE-1);
|
||||||
|
size_t mod_size = (mod+1) << lg_delta;
|
||||||
|
|
||||||
|
size_t sz = grp_size + mod_size;
|
||||||
|
return (sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE size_t
|
||||||
|
pind2sz_lookup(pszind_t pind)
|
||||||
|
{
|
||||||
|
size_t ret = (size_t)pind2sz_tab[pind];
|
||||||
|
assert(ret == pind2sz_compute(pind));
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE size_t
|
||||||
|
pind2sz(pszind_t pind)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(pind < NPSIZES);
|
||||||
|
return (pind2sz_lookup(pind));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE size_t
|
||||||
|
psz2u(size_t psz)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (unlikely(psz > HUGE_MAXCLASS))
|
||||||
|
return (0);
|
||||||
|
{
|
||||||
|
size_t x = lg_floor((psz<<1)-1);
|
||||||
|
size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ?
|
||||||
|
LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1;
|
||||||
|
size_t delta = ZU(1) << lg_delta;
|
||||||
|
size_t delta_mask = delta - 1;
|
||||||
|
size_t usize = (psz + delta_mask) & ~delta_mask;
|
||||||
|
return (usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JEMALLOC_INLINE szind_t
|
JEMALLOC_INLINE szind_t
|
||||||
size2index_compute(size_t size)
|
size2index_compute(size_t size)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (unlikely(size > HUGE_MAXCLASS))
|
||||||
|
return (NSIZES);
|
||||||
#if (NTBINS != 0)
|
#if (NTBINS != 0)
|
||||||
if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
|
if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
|
||||||
szind_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
|
szind_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
|
||||||
@@ -575,9 +675,7 @@ size2index_compute(size_t size)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
szind_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?
|
szind_t x = lg_floor((size<<1)-1);
|
||||||
(ZU(1)<<(LG_SIZEOF_PTR+3)) : ((ZU(1)<<(LG_SIZEOF_PTR+3))-1))
|
|
||||||
: lg_floor((size<<1)-1);
|
|
||||||
szind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 :
|
szind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 :
|
||||||
x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM);
|
x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM);
|
||||||
szind_t grp = shift << LG_SIZE_CLASS_GROUP;
|
szind_t grp = shift << LG_SIZE_CLASS_GROUP;
|
||||||
@@ -663,6 +761,8 @@ JEMALLOC_ALWAYS_INLINE size_t
|
|||||||
s2u_compute(size_t size)
|
s2u_compute(size_t size)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (unlikely(size > HUGE_MAXCLASS))
|
||||||
|
return (0);
|
||||||
#if (NTBINS > 0)
|
#if (NTBINS > 0)
|
||||||
if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
|
if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
|
||||||
size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
|
size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
|
||||||
@@ -672,9 +772,7 @@ s2u_compute(size_t size)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
size_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?
|
size_t x = lg_floor((size<<1)-1);
|
||||||
(ZU(1)<<(LG_SIZEOF_PTR+3)) : ((ZU(1)<<(LG_SIZEOF_PTR+3))-1))
|
|
||||||
: lg_floor((size<<1)-1);
|
|
||||||
size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)
|
size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)
|
||||||
? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;
|
? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;
|
||||||
size_t delta = ZU(1) << lg_delta;
|
size_t delta = ZU(1) << lg_delta;
|
||||||
@@ -754,7 +852,7 @@ sa2u(size_t size, size_t alignment)
|
|||||||
* Calculate the size of the over-size run that arena_palloc()
|
* Calculate the size of the over-size run that arena_palloc()
|
||||||
* would need to allocate in order to guarantee the alignment.
|
* would need to allocate in order to guarantee the alignment.
|
||||||
*/
|
*/
|
||||||
if (usize + large_pad + alignment <= arena_maxrun)
|
if (usize + large_pad + alignment - PAGE <= arena_maxrun)
|
||||||
return (usize);
|
return (usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,7 +882,7 @@ sa2u(size_t size, size_t alignment)
|
|||||||
* Calculate the multi-chunk mapping that huge_palloc() would need in
|
* Calculate the multi-chunk mapping that huge_palloc() would need in
|
||||||
* order to guarantee the alignment.
|
* order to guarantee the alignment.
|
||||||
*/
|
*/
|
||||||
if (usize + alignment < usize) {
|
if (usize + alignment - PAGE < usize) {
|
||||||
/* size_t overflow. */
|
/* size_t overflow. */
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -815,14 +913,10 @@ arena_choose(tsd_t *tsd, arena_t *arena)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_INLINE arena_t *
|
JEMALLOC_INLINE arena_t *
|
||||||
arena_ichoose(tsdn_t *tsdn, arena_t *arena)
|
arena_ichoose(tsd_t *tsd, arena_t *arena)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert(!tsdn_null(tsdn) || arena != NULL);
|
return (arena_choose_impl(tsd, arena, true));
|
||||||
|
|
||||||
if (!tsdn_null(tsdn))
|
|
||||||
return (arena_choose_impl(tsdn_tsd(tsdn), NULL, true));
|
|
||||||
return (arena);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_INLINE arena_tdata_t *
|
JEMALLOC_INLINE arena_tdata_t *
|
||||||
|
|||||||
@@ -17,8 +17,18 @@
|
|||||||
# include <sys/uio.h>
|
# include <sys/uio.h>
|
||||||
# endif
|
# endif
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
|
# ifdef JEMALLOC_OS_UNFAIR_LOCK
|
||||||
|
# include <os/lock.h>
|
||||||
|
# endif
|
||||||
|
# ifdef JEMALLOC_GLIBC_MALLOC_HOOK
|
||||||
|
# include <sched.h>
|
||||||
|
# endif
|
||||||
# include <errno.h>
|
# include <errno.h>
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
|
# include <time.h>
|
||||||
|
# ifdef JEMALLOC_HAVE_MACH_ABSOLUTE_TIME
|
||||||
|
# include <mach/mach_time.h>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|||||||
@@ -56,9 +56,9 @@
|
|||||||
#undef JEMALLOC_HAVE_BUILTIN_CLZ
|
#undef JEMALLOC_HAVE_BUILTIN_CLZ
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Defined if madvise(2) is available.
|
* Defined if os_unfair_lock_*() functions are available, as provided by Darwin.
|
||||||
*/
|
*/
|
||||||
#undef JEMALLOC_HAVE_MADVISE
|
#undef JEMALLOC_OS_UNFAIR_LOCK
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Defined if OSSpin*() functions are available, as provided by Darwin, and
|
* Defined if OSSpin*() functions are available, as provided by Darwin, and
|
||||||
@@ -66,6 +66,9 @@
|
|||||||
*/
|
*/
|
||||||
#undef JEMALLOC_OSSPIN
|
#undef JEMALLOC_OSSPIN
|
||||||
|
|
||||||
|
/* Defined if syscall(2) is usable. */
|
||||||
|
#undef JEMALLOC_USE_SYSCALL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Defined if secure_getenv(3) is available.
|
* Defined if secure_getenv(3) is available.
|
||||||
*/
|
*/
|
||||||
@@ -76,6 +79,24 @@
|
|||||||
*/
|
*/
|
||||||
#undef JEMALLOC_HAVE_ISSETUGID
|
#undef JEMALLOC_HAVE_ISSETUGID
|
||||||
|
|
||||||
|
/* Defined if pthread_atfork(3) is available. */
|
||||||
|
#undef JEMALLOC_HAVE_PTHREAD_ATFORK
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined if clock_gettime(CLOCK_MONOTONIC_COARSE, ...) is available.
|
||||||
|
*/
|
||||||
|
#undef JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined if clock_gettime(CLOCK_MONOTONIC, ...) is available.
|
||||||
|
*/
|
||||||
|
#undef JEMALLOC_HAVE_CLOCK_MONOTONIC
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined if mach_absolute_time() is available.
|
||||||
|
*/
|
||||||
|
#undef JEMALLOC_HAVE_MACH_ABSOLUTE_TIME
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Defined if _malloc_thread_cleanup() exists. At least in the case of
|
* Defined if _malloc_thread_cleanup() exists. At least in the case of
|
||||||
* FreeBSD, pthread_key_create() allocates, which if used during malloc
|
* FreeBSD, pthread_key_create() allocates, which if used during malloc
|
||||||
@@ -188,6 +209,12 @@
|
|||||||
/* TLS is used to map arenas and magazine caches to threads. */
|
/* TLS is used to map arenas and magazine caches to threads. */
|
||||||
#undef JEMALLOC_TLS
|
#undef JEMALLOC_TLS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to mark unreachable code to quiet "end of non-void" compiler warnings.
|
||||||
|
* Don't use this directly; instead use unreachable() from util.h
|
||||||
|
*/
|
||||||
|
#undef JEMALLOC_INTERNAL_UNREACHABLE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ffs*() functions to use for bitmapping. Don't use these directly; instead,
|
* ffs*() functions to use for bitmapping. Don't use these directly; instead,
|
||||||
* use ffs_*() from util.h.
|
* use ffs_*() from util.h.
|
||||||
@@ -223,18 +250,26 @@
|
|||||||
#undef JEMALLOC_SYSCTL_VM_OVERCOMMIT
|
#undef JEMALLOC_SYSCTL_VM_OVERCOMMIT
|
||||||
#undef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY
|
#undef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY
|
||||||
|
|
||||||
|
/* Defined if madvise(2) is available. */
|
||||||
|
#undef JEMALLOC_HAVE_MADVISE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Methods for purging unused pages differ between operating systems.
|
* Methods for purging unused pages differ between operating systems.
|
||||||
*
|
*
|
||||||
* madvise(..., MADV_DONTNEED) : On Linux, this immediately discards pages,
|
* madvise(..., MADV_FREE) : This marks pages as being unused, such that they
|
||||||
* such that new pages will be demand-zeroed if
|
* will be discarded rather than swapped out.
|
||||||
* the address region is later touched.
|
* madvise(..., MADV_DONTNEED) : This immediately discards pages, such that
|
||||||
* madvise(..., MADV_FREE) : On FreeBSD and Darwin, this marks pages as being
|
* new pages will be demand-zeroed if the
|
||||||
* unused, such that they will be discarded rather
|
* address region is later touched.
|
||||||
* than swapped out.
|
|
||||||
*/
|
*/
|
||||||
#undef JEMALLOC_PURGE_MADVISE_DONTNEED
|
|
||||||
#undef JEMALLOC_PURGE_MADVISE_FREE
|
#undef JEMALLOC_PURGE_MADVISE_FREE
|
||||||
|
#undef JEMALLOC_PURGE_MADVISE_DONTNEED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined if transparent huge pages are supported via the MADV_[NO]HUGEPAGE
|
||||||
|
* arguments to madvise(2).
|
||||||
|
*/
|
||||||
|
#undef JEMALLOC_THP
|
||||||
|
|
||||||
/* Define if operating system has alloca.h header. */
|
/* Define if operating system has alloca.h header. */
|
||||||
#undef JEMALLOC_HAS_ALLOCA_H
|
#undef JEMALLOC_HAS_ALLOCA_H
|
||||||
|
|||||||
@@ -105,8 +105,8 @@ mb_write(void)
|
|||||||
malloc_mutex_t mtx;
|
malloc_mutex_t mtx;
|
||||||
|
|
||||||
malloc_mutex_init(&mtx, "mb", WITNESS_RANK_OMIT);
|
malloc_mutex_init(&mtx, "mb", WITNESS_RANK_OMIT);
|
||||||
malloc_mutex_lock(NULL, &mtx);
|
malloc_mutex_lock(TSDN_NULL, &mtx);
|
||||||
malloc_mutex_unlock(NULL, &mtx);
|
malloc_mutex_unlock(TSDN_NULL, &mtx);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ typedef struct malloc_mutex_s malloc_mutex_t;
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# define MALLOC_MUTEX_INITIALIZER
|
# define MALLOC_MUTEX_INITIALIZER
|
||||||
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
||||||
|
# define MALLOC_MUTEX_INITIALIZER \
|
||||||
|
{OS_UNFAIR_LOCK_INIT, WITNESS_INITIALIZER(WITNESS_RANK_OMIT)}
|
||||||
#elif (defined(JEMALLOC_OSSPIN))
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
# define MALLOC_MUTEX_INITIALIZER {0, WITNESS_INITIALIZER(WITNESS_RANK_OMIT)}
|
# define MALLOC_MUTEX_INITIALIZER {0, WITNESS_INITIALIZER(WITNESS_RANK_OMIT)}
|
||||||
#elif (defined(JEMALLOC_MUTEX_INIT_CB))
|
#elif (defined(JEMALLOC_MUTEX_INIT_CB))
|
||||||
@@ -35,6 +38,8 @@ struct malloc_mutex_s {
|
|||||||
# else
|
# else
|
||||||
CRITICAL_SECTION lock;
|
CRITICAL_SECTION lock;
|
||||||
# endif
|
# endif
|
||||||
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
||||||
|
os_unfair_lock lock;
|
||||||
#elif (defined(JEMALLOC_OSSPIN))
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
OSSpinLock lock;
|
OSSpinLock lock;
|
||||||
#elif (defined(JEMALLOC_MUTEX_INIT_CB))
|
#elif (defined(JEMALLOC_MUTEX_INIT_CB))
|
||||||
@@ -88,6 +93,8 @@ malloc_mutex_lock(tsdn_t *tsdn, malloc_mutex_t *mutex)
|
|||||||
# else
|
# else
|
||||||
EnterCriticalSection(&mutex->lock);
|
EnterCriticalSection(&mutex->lock);
|
||||||
# endif
|
# endif
|
||||||
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
||||||
|
os_unfair_lock_lock(&mutex->lock);
|
||||||
#elif (defined(JEMALLOC_OSSPIN))
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
OSSpinLockLock(&mutex->lock);
|
OSSpinLockLock(&mutex->lock);
|
||||||
#else
|
#else
|
||||||
@@ -109,6 +116,8 @@ malloc_mutex_unlock(tsdn_t *tsdn, malloc_mutex_t *mutex)
|
|||||||
# else
|
# else
|
||||||
LeaveCriticalSection(&mutex->lock);
|
LeaveCriticalSection(&mutex->lock);
|
||||||
# endif
|
# endif
|
||||||
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
||||||
|
os_unfair_lock_unlock(&mutex->lock);
|
||||||
#elif (defined(JEMALLOC_OSSPIN))
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
OSSpinLockUnlock(&mutex->lock);
|
OSSpinLockUnlock(&mutex->lock);
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
#ifdef JEMALLOC_H_TYPES
|
#ifdef JEMALLOC_H_TYPES
|
||||||
|
|
||||||
#define JEMALLOC_CLOCK_GETTIME defined(_POSIX_MONOTONIC_CLOCK) \
|
|
||||||
&& _POSIX_MONOTONIC_CLOCK >= 0
|
|
||||||
|
|
||||||
typedef struct nstime_s nstime_t;
|
typedef struct nstime_s nstime_t;
|
||||||
|
|
||||||
/* Maximum supported number of seconds (~584 years). */
|
/* Maximum supported number of seconds (~584 years). */
|
||||||
@@ -34,9 +31,12 @@ void nstime_imultiply(nstime_t *time, uint64_t multiplier);
|
|||||||
void nstime_idivide(nstime_t *time, uint64_t divisor);
|
void nstime_idivide(nstime_t *time, uint64_t divisor);
|
||||||
uint64_t nstime_divide(const nstime_t *time, const nstime_t *divisor);
|
uint64_t nstime_divide(const nstime_t *time, const nstime_t *divisor);
|
||||||
#ifdef JEMALLOC_JET
|
#ifdef JEMALLOC_JET
|
||||||
|
typedef bool (nstime_monotonic_t)(void);
|
||||||
|
extern nstime_monotonic_t *nstime_monotonic;
|
||||||
typedef bool (nstime_update_t)(nstime_t *);
|
typedef bool (nstime_update_t)(nstime_t *);
|
||||||
extern nstime_update_t *nstime_update;
|
extern nstime_update_t *nstime_update;
|
||||||
#else
|
#else
|
||||||
|
bool nstime_monotonic(void);
|
||||||
bool nstime_update(nstime_t *time);
|
bool nstime_update(nstime_t *time);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ void *pages_trim(void *addr, size_t alloc_size, size_t leadsize,
|
|||||||
bool pages_commit(void *addr, size_t size);
|
bool pages_commit(void *addr, size_t size);
|
||||||
bool pages_decommit(void *addr, size_t size);
|
bool pages_decommit(void *addr, size_t size);
|
||||||
bool pages_purge(void *addr, size_t size);
|
bool pages_purge(void *addr, size_t size);
|
||||||
|
bool pages_huge(void *addr, size_t size);
|
||||||
|
bool pages_nohuge(void *addr, size_t size);
|
||||||
void pages_boot(void);
|
void pages_boot(void);
|
||||||
|
|
||||||
#endif /* JEMALLOC_H_EXTERNS */
|
#endif /* JEMALLOC_H_EXTERNS */
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
a0dalloc
|
a0dalloc
|
||||||
|
a0get
|
||||||
a0malloc
|
a0malloc
|
||||||
arena_aalloc
|
arena_aalloc
|
||||||
arena_alloc_junk_small
|
arena_alloc_junk_small
|
||||||
@@ -35,6 +36,7 @@ arena_decay_time_get
|
|||||||
arena_decay_time_set
|
arena_decay_time_set
|
||||||
arena_dss_prec_get
|
arena_dss_prec_get
|
||||||
arena_dss_prec_set
|
arena_dss_prec_set
|
||||||
|
arena_extent_sn_next
|
||||||
arena_get
|
arena_get
|
||||||
arena_ichoose
|
arena_ichoose
|
||||||
arena_init
|
arena_init
|
||||||
@@ -167,20 +169,15 @@ chunk_dalloc_mmap
|
|||||||
chunk_dalloc_wrapper
|
chunk_dalloc_wrapper
|
||||||
chunk_deregister
|
chunk_deregister
|
||||||
chunk_dss_boot
|
chunk_dss_boot
|
||||||
chunk_dss_postfork_child
|
chunk_dss_mergeable
|
||||||
chunk_dss_postfork_parent
|
|
||||||
chunk_dss_prec_get
|
chunk_dss_prec_get
|
||||||
chunk_dss_prec_set
|
chunk_dss_prec_set
|
||||||
chunk_dss_prefork
|
|
||||||
chunk_hooks_default
|
chunk_hooks_default
|
||||||
chunk_hooks_get
|
chunk_hooks_get
|
||||||
chunk_hooks_set
|
chunk_hooks_set
|
||||||
chunk_in_dss
|
chunk_in_dss
|
||||||
chunk_lookup
|
chunk_lookup
|
||||||
chunk_npages
|
chunk_npages
|
||||||
chunk_postfork_child
|
|
||||||
chunk_postfork_parent
|
|
||||||
chunk_prefork
|
|
||||||
chunk_purge_wrapper
|
chunk_purge_wrapper
|
||||||
chunk_register
|
chunk_register
|
||||||
chunks_rtree
|
chunks_rtree
|
||||||
@@ -222,6 +219,8 @@ extent_node_prof_tctx_get
|
|||||||
extent_node_prof_tctx_set
|
extent_node_prof_tctx_set
|
||||||
extent_node_size_get
|
extent_node_size_get
|
||||||
extent_node_size_set
|
extent_node_size_set
|
||||||
|
extent_node_sn_get
|
||||||
|
extent_node_sn_set
|
||||||
extent_node_zeroed_get
|
extent_node_zeroed_get
|
||||||
extent_node_zeroed_set
|
extent_node_zeroed_set
|
||||||
extent_tree_ad_destroy
|
extent_tree_ad_destroy
|
||||||
@@ -243,25 +242,25 @@ extent_tree_ad_reverse_iter
|
|||||||
extent_tree_ad_reverse_iter_recurse
|
extent_tree_ad_reverse_iter_recurse
|
||||||
extent_tree_ad_reverse_iter_start
|
extent_tree_ad_reverse_iter_start
|
||||||
extent_tree_ad_search
|
extent_tree_ad_search
|
||||||
extent_tree_szad_destroy
|
extent_tree_szsnad_destroy
|
||||||
extent_tree_szad_destroy_recurse
|
extent_tree_szsnad_destroy_recurse
|
||||||
extent_tree_szad_empty
|
extent_tree_szsnad_empty
|
||||||
extent_tree_szad_first
|
extent_tree_szsnad_first
|
||||||
extent_tree_szad_insert
|
extent_tree_szsnad_insert
|
||||||
extent_tree_szad_iter
|
extent_tree_szsnad_iter
|
||||||
extent_tree_szad_iter_recurse
|
extent_tree_szsnad_iter_recurse
|
||||||
extent_tree_szad_iter_start
|
extent_tree_szsnad_iter_start
|
||||||
extent_tree_szad_last
|
extent_tree_szsnad_last
|
||||||
extent_tree_szad_new
|
extent_tree_szsnad_new
|
||||||
extent_tree_szad_next
|
extent_tree_szsnad_next
|
||||||
extent_tree_szad_nsearch
|
extent_tree_szsnad_nsearch
|
||||||
extent_tree_szad_prev
|
extent_tree_szsnad_prev
|
||||||
extent_tree_szad_psearch
|
extent_tree_szsnad_psearch
|
||||||
extent_tree_szad_remove
|
extent_tree_szsnad_remove
|
||||||
extent_tree_szad_reverse_iter
|
extent_tree_szsnad_reverse_iter
|
||||||
extent_tree_szad_reverse_iter_recurse
|
extent_tree_szsnad_reverse_iter_recurse
|
||||||
extent_tree_szad_reverse_iter_start
|
extent_tree_szsnad_reverse_iter_start
|
||||||
extent_tree_szad_search
|
extent_tree_szsnad_search
|
||||||
ffs_llu
|
ffs_llu
|
||||||
ffs_lu
|
ffs_lu
|
||||||
ffs_u
|
ffs_u
|
||||||
@@ -360,6 +359,7 @@ nstime_idivide
|
|||||||
nstime_imultiply
|
nstime_imultiply
|
||||||
nstime_init
|
nstime_init
|
||||||
nstime_init2
|
nstime_init2
|
||||||
|
nstime_monotonic
|
||||||
nstime_ns
|
nstime_ns
|
||||||
nstime_nsec
|
nstime_nsec
|
||||||
nstime_sec
|
nstime_sec
|
||||||
@@ -397,15 +397,28 @@ p2rz
|
|||||||
pages_boot
|
pages_boot
|
||||||
pages_commit
|
pages_commit
|
||||||
pages_decommit
|
pages_decommit
|
||||||
|
pages_huge
|
||||||
pages_map
|
pages_map
|
||||||
|
pages_nohuge
|
||||||
pages_purge
|
pages_purge
|
||||||
pages_trim
|
pages_trim
|
||||||
pages_unmap
|
pages_unmap
|
||||||
|
pind2sz
|
||||||
|
pind2sz_compute
|
||||||
|
pind2sz_lookup
|
||||||
|
pind2sz_tab
|
||||||
pow2_ceil_u32
|
pow2_ceil_u32
|
||||||
pow2_ceil_u64
|
pow2_ceil_u64
|
||||||
pow2_ceil_zu
|
pow2_ceil_zu
|
||||||
prng_lg_range
|
prng_lg_range_u32
|
||||||
prng_range
|
prng_lg_range_u64
|
||||||
|
prng_lg_range_zu
|
||||||
|
prng_range_u32
|
||||||
|
prng_range_u64
|
||||||
|
prng_range_zu
|
||||||
|
prng_state_next_u32
|
||||||
|
prng_state_next_u64
|
||||||
|
prng_state_next_zu
|
||||||
prof_active
|
prof_active
|
||||||
prof_active_get
|
prof_active_get
|
||||||
prof_active_get_unlocked
|
prof_active_get_unlocked
|
||||||
@@ -454,12 +467,13 @@ prof_thread_active_init_set
|
|||||||
prof_thread_active_set
|
prof_thread_active_set
|
||||||
prof_thread_name_get
|
prof_thread_name_get
|
||||||
prof_thread_name_set
|
prof_thread_name_set
|
||||||
|
psz2ind
|
||||||
|
psz2u
|
||||||
purge_mode_names
|
purge_mode_names
|
||||||
quarantine
|
quarantine
|
||||||
quarantine_alloc_hook
|
quarantine_alloc_hook
|
||||||
quarantine_alloc_hook_work
|
quarantine_alloc_hook_work
|
||||||
quarantine_cleanup
|
quarantine_cleanup
|
||||||
register_zone
|
|
||||||
rtree_child_read
|
rtree_child_read
|
||||||
rtree_child_read_hard
|
rtree_child_read_hard
|
||||||
rtree_child_tryread
|
rtree_child_tryread
|
||||||
@@ -477,7 +491,6 @@ rtree_val_read
|
|||||||
rtree_val_write
|
rtree_val_write
|
||||||
run_quantize_ceil
|
run_quantize_ceil
|
||||||
run_quantize_floor
|
run_quantize_floor
|
||||||
run_quantize_max
|
|
||||||
s2u
|
s2u
|
||||||
s2u_compute
|
s2u_compute
|
||||||
s2u_lookup
|
s2u_lookup
|
||||||
@@ -487,6 +500,8 @@ size2index
|
|||||||
size2index_compute
|
size2index_compute
|
||||||
size2index_lookup
|
size2index_lookup
|
||||||
size2index_tab
|
size2index_tab
|
||||||
|
spin_adaptive
|
||||||
|
spin_init
|
||||||
stats_cactive
|
stats_cactive
|
||||||
stats_cactive_add
|
stats_cactive_add
|
||||||
stats_cactive_get
|
stats_cactive_get
|
||||||
@@ -545,7 +560,9 @@ tsd_booted_get
|
|||||||
tsd_cleanup
|
tsd_cleanup
|
||||||
tsd_cleanup_wrapper
|
tsd_cleanup_wrapper
|
||||||
tsd_fetch
|
tsd_fetch
|
||||||
|
tsd_fetch_impl
|
||||||
tsd_get
|
tsd_get
|
||||||
|
tsd_get_allocates
|
||||||
tsd_iarena_get
|
tsd_iarena_get
|
||||||
tsd_iarena_set
|
tsd_iarena_set
|
||||||
tsd_iarenap_get
|
tsd_iarenap_get
|
||||||
@@ -604,9 +621,11 @@ witness_lock
|
|||||||
witness_lock_error
|
witness_lock_error
|
||||||
witness_lockless_error
|
witness_lockless_error
|
||||||
witness_not_owner_error
|
witness_not_owner_error
|
||||||
|
witness_owner
|
||||||
witness_owner_error
|
witness_owner_error
|
||||||
witness_postfork_child
|
witness_postfork_child
|
||||||
witness_postfork_parent
|
witness_postfork_parent
|
||||||
witness_prefork
|
witness_prefork
|
||||||
witness_unlock
|
witness_unlock
|
||||||
witnesses_cleanup
|
witnesses_cleanup
|
||||||
|
zone_register
|
||||||
|
|||||||
@@ -19,8 +19,12 @@
|
|||||||
* the next has a cycle of 4, etc. For this reason, we prefer to use the upper
|
* the next has a cycle of 4, etc. For this reason, we prefer to use the upper
|
||||||
* bits.
|
* bits.
|
||||||
*/
|
*/
|
||||||
#define PRNG_A UINT64_C(6364136223846793005)
|
|
||||||
#define PRNG_C UINT64_C(1442695040888963407)
|
#define PRNG_A_32 UINT32_C(1103515241)
|
||||||
|
#define PRNG_C_32 UINT32_C(12347)
|
||||||
|
|
||||||
|
#define PRNG_A_64 UINT64_C(6364136223846793005)
|
||||||
|
#define PRNG_C_64 UINT64_C(1442695040888963407)
|
||||||
|
|
||||||
#endif /* JEMALLOC_H_TYPES */
|
#endif /* JEMALLOC_H_TYPES */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@@ -35,28 +39,133 @@
|
|||||||
#ifdef JEMALLOC_H_INLINES
|
#ifdef JEMALLOC_H_INLINES
|
||||||
|
|
||||||
#ifndef JEMALLOC_ENABLE_INLINE
|
#ifndef JEMALLOC_ENABLE_INLINE
|
||||||
uint64_t prng_lg_range(uint64_t *state, unsigned lg_range);
|
uint32_t prng_state_next_u32(uint32_t state);
|
||||||
uint64_t prng_range(uint64_t *state, uint64_t range);
|
uint64_t prng_state_next_u64(uint64_t state);
|
||||||
|
size_t prng_state_next_zu(size_t state);
|
||||||
|
|
||||||
|
uint32_t prng_lg_range_u32(uint32_t *state, unsigned lg_range,
|
||||||
|
bool atomic);
|
||||||
|
uint64_t prng_lg_range_u64(uint64_t *state, unsigned lg_range);
|
||||||
|
size_t prng_lg_range_zu(size_t *state, unsigned lg_range, bool atomic);
|
||||||
|
|
||||||
|
uint32_t prng_range_u32(uint32_t *state, uint32_t range, bool atomic);
|
||||||
|
uint64_t prng_range_u64(uint64_t *state, uint64_t range);
|
||||||
|
size_t prng_range_zu(size_t *state, size_t range, bool atomic);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PRNG_C_))
|
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PRNG_C_))
|
||||||
JEMALLOC_ALWAYS_INLINE uint64_t
|
JEMALLOC_ALWAYS_INLINE uint32_t
|
||||||
prng_lg_range(uint64_t *state, unsigned lg_range)
|
prng_state_next_u32(uint32_t state)
|
||||||
{
|
{
|
||||||
uint64_t ret;
|
|
||||||
|
return ((state * PRNG_A_32) + PRNG_C_32);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_ALWAYS_INLINE uint64_t
|
||||||
|
prng_state_next_u64(uint64_t state)
|
||||||
|
{
|
||||||
|
|
||||||
|
return ((state * PRNG_A_64) + PRNG_C_64);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_ALWAYS_INLINE size_t
|
||||||
|
prng_state_next_zu(size_t state)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if LG_SIZEOF_PTR == 2
|
||||||
|
return ((state * PRNG_A_32) + PRNG_C_32);
|
||||||
|
#elif LG_SIZEOF_PTR == 3
|
||||||
|
return ((state * PRNG_A_64) + PRNG_C_64);
|
||||||
|
#else
|
||||||
|
#error Unsupported pointer size
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_ALWAYS_INLINE uint32_t
|
||||||
|
prng_lg_range_u32(uint32_t *state, unsigned lg_range, bool atomic)
|
||||||
|
{
|
||||||
|
uint32_t ret, state1;
|
||||||
|
|
||||||
|
assert(lg_range > 0);
|
||||||
|
assert(lg_range <= 32);
|
||||||
|
|
||||||
|
if (atomic) {
|
||||||
|
uint32_t state0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
state0 = atomic_read_uint32(state);
|
||||||
|
state1 = prng_state_next_u32(state0);
|
||||||
|
} while (atomic_cas_uint32(state, state0, state1));
|
||||||
|
} else {
|
||||||
|
state1 = prng_state_next_u32(*state);
|
||||||
|
*state = state1;
|
||||||
|
}
|
||||||
|
ret = state1 >> (32 - lg_range);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 64-bit atomic operations cannot be supported on all relevant platforms. */
|
||||||
|
JEMALLOC_ALWAYS_INLINE uint64_t
|
||||||
|
prng_lg_range_u64(uint64_t *state, unsigned lg_range)
|
||||||
|
{
|
||||||
|
uint64_t ret, state1;
|
||||||
|
|
||||||
assert(lg_range > 0);
|
assert(lg_range > 0);
|
||||||
assert(lg_range <= 64);
|
assert(lg_range <= 64);
|
||||||
|
|
||||||
ret = (*state * PRNG_A) + PRNG_C;
|
state1 = prng_state_next_u64(*state);
|
||||||
*state = ret;
|
*state = state1;
|
||||||
ret >>= (64 - lg_range);
|
ret = state1 >> (64 - lg_range);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_ALWAYS_INLINE size_t
|
||||||
|
prng_lg_range_zu(size_t *state, unsigned lg_range, bool atomic)
|
||||||
|
{
|
||||||
|
size_t ret, state1;
|
||||||
|
|
||||||
|
assert(lg_range > 0);
|
||||||
|
assert(lg_range <= ZU(1) << (3 + LG_SIZEOF_PTR));
|
||||||
|
|
||||||
|
if (atomic) {
|
||||||
|
size_t state0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
state0 = atomic_read_z(state);
|
||||||
|
state1 = prng_state_next_zu(state0);
|
||||||
|
} while (atomic_cas_z(state, state0, state1));
|
||||||
|
} else {
|
||||||
|
state1 = prng_state_next_zu(*state);
|
||||||
|
*state = state1;
|
||||||
|
}
|
||||||
|
ret = state1 >> ((ZU(1) << (3 + LG_SIZEOF_PTR)) - lg_range);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_ALWAYS_INLINE uint32_t
|
||||||
|
prng_range_u32(uint32_t *state, uint32_t range, bool atomic)
|
||||||
|
{
|
||||||
|
uint32_t ret;
|
||||||
|
unsigned lg_range;
|
||||||
|
|
||||||
|
assert(range > 1);
|
||||||
|
|
||||||
|
/* Compute the ceiling of lg(range). */
|
||||||
|
lg_range = ffs_u32(pow2_ceil_u32(range)) - 1;
|
||||||
|
|
||||||
|
/* Generate a result in [0..range) via repeated trial. */
|
||||||
|
do {
|
||||||
|
ret = prng_lg_range_u32(state, lg_range, atomic);
|
||||||
|
} while (ret >= range);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE uint64_t
|
JEMALLOC_ALWAYS_INLINE uint64_t
|
||||||
prng_range(uint64_t *state, uint64_t range)
|
prng_range_u64(uint64_t *state, uint64_t range)
|
||||||
{
|
{
|
||||||
uint64_t ret;
|
uint64_t ret;
|
||||||
unsigned lg_range;
|
unsigned lg_range;
|
||||||
@@ -68,7 +177,26 @@ prng_range(uint64_t *state, uint64_t range)
|
|||||||
|
|
||||||
/* Generate a result in [0..range) via repeated trial. */
|
/* Generate a result in [0..range) via repeated trial. */
|
||||||
do {
|
do {
|
||||||
ret = prng_lg_range(state, lg_range);
|
ret = prng_lg_range_u64(state, lg_range);
|
||||||
|
} while (ret >= range);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_ALWAYS_INLINE size_t
|
||||||
|
prng_range_zu(size_t *state, size_t range, bool atomic)
|
||||||
|
{
|
||||||
|
size_t ret;
|
||||||
|
unsigned lg_range;
|
||||||
|
|
||||||
|
assert(range > 1);
|
||||||
|
|
||||||
|
/* Compute the ceiling of lg(range). */
|
||||||
|
lg_range = ffs_u64(pow2_ceil_u64(range)) - 1;
|
||||||
|
|
||||||
|
/* Generate a result in [0..range) via repeated trial. */
|
||||||
|
do {
|
||||||
|
ret = prng_lg_range_zu(state, lg_range, atomic);
|
||||||
} while (ret >= range);
|
} while (ret >= range);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
|
|||||||
@@ -299,9 +299,9 @@ extern prof_dump_header_t *prof_dump_header;
|
|||||||
void prof_idump(tsdn_t *tsdn);
|
void prof_idump(tsdn_t *tsdn);
|
||||||
bool prof_mdump(tsd_t *tsd, const char *filename);
|
bool prof_mdump(tsd_t *tsd, const char *filename);
|
||||||
void prof_gdump(tsdn_t *tsdn);
|
void prof_gdump(tsdn_t *tsdn);
|
||||||
prof_tdata_t *prof_tdata_init(tsdn_t *tsdn);
|
prof_tdata_t *prof_tdata_init(tsd_t *tsd);
|
||||||
prof_tdata_t *prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata);
|
prof_tdata_t *prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata);
|
||||||
void prof_reset(tsdn_t *tsdn, size_t lg_sample);
|
void prof_reset(tsd_t *tsd, size_t lg_sample);
|
||||||
void prof_tdata_cleanup(tsd_t *tsd);
|
void prof_tdata_cleanup(tsd_t *tsd);
|
||||||
bool prof_active_get(tsdn_t *tsdn);
|
bool prof_active_get(tsdn_t *tsdn);
|
||||||
bool prof_active_set(tsdn_t *tsdn, bool active);
|
bool prof_active_set(tsdn_t *tsdn, bool active);
|
||||||
@@ -315,7 +315,7 @@ bool prof_gdump_get(tsdn_t *tsdn);
|
|||||||
bool prof_gdump_set(tsdn_t *tsdn, bool active);
|
bool prof_gdump_set(tsdn_t *tsdn, bool active);
|
||||||
void prof_boot0(void);
|
void prof_boot0(void);
|
||||||
void prof_boot1(void);
|
void prof_boot1(void);
|
||||||
bool prof_boot2(tsdn_t *tsdn);
|
bool prof_boot2(tsd_t *tsd);
|
||||||
void prof_prefork0(tsdn_t *tsdn);
|
void prof_prefork0(tsdn_t *tsdn);
|
||||||
void prof_prefork1(tsdn_t *tsdn);
|
void prof_prefork1(tsdn_t *tsdn);
|
||||||
void prof_postfork_parent(tsdn_t *tsdn);
|
void prof_postfork_parent(tsdn_t *tsdn);
|
||||||
@@ -384,7 +384,7 @@ prof_tdata_get(tsd_t *tsd, bool create)
|
|||||||
if (create) {
|
if (create) {
|
||||||
if (unlikely(tdata == NULL)) {
|
if (unlikely(tdata == NULL)) {
|
||||||
if (tsd_nominal(tsd)) {
|
if (tsd_nominal(tsd)) {
|
||||||
tdata = prof_tdata_init(tsd_tsdn(tsd));
|
tdata = prof_tdata_init(tsd);
|
||||||
tsd_prof_tdata_set(tsd, tdata);
|
tsd_prof_tdata_set(tsd, tdata);
|
||||||
}
|
}
|
||||||
} else if (unlikely(tdata->expired)) {
|
} else if (unlikely(tdata->expired)) {
|
||||||
@@ -513,6 +513,7 @@ prof_realloc(tsd_t *tsd, const void *ptr, size_t usize, prof_tctx_t *tctx,
|
|||||||
* though its actual usize was insufficient to cross the
|
* though its actual usize was insufficient to cross the
|
||||||
* sample threshold.
|
* sample threshold.
|
||||||
*/
|
*/
|
||||||
|
prof_alloc_rollback(tsd, tctx, true);
|
||||||
tctx = (prof_tctx_t *)(uintptr_t)1U;
|
tctx = (prof_tctx_t *)(uintptr_t)1U;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,21 @@ size_class() {
|
|||||||
lg_p=$5
|
lg_p=$5
|
||||||
lg_kmax=$6
|
lg_kmax=$6
|
||||||
|
|
||||||
|
if [ ${lg_delta} -ge ${lg_p} ] ; then
|
||||||
|
psz="yes"
|
||||||
|
else
|
||||||
|
pow2 ${lg_p}; p=${pow2_result}
|
||||||
|
pow2 ${lg_grp}; grp=${pow2_result}
|
||||||
|
pow2 ${lg_delta}; delta=${pow2_result}
|
||||||
|
sz=$((${grp} + ${delta} * ${ndelta}))
|
||||||
|
npgs=$((${sz} / ${p}))
|
||||||
|
if [ ${sz} -eq $((${npgs} * ${p})) ] ; then
|
||||||
|
psz="yes"
|
||||||
|
else
|
||||||
|
psz="no"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
lg ${ndelta}; lg_ndelta=${lg_result}; pow2 ${lg_ndelta}
|
lg ${ndelta}; lg_ndelta=${lg_result}; pow2 ${lg_ndelta}
|
||||||
if [ ${pow2_result} -lt ${ndelta} ] ; then
|
if [ ${pow2_result} -lt ${ndelta} ] ; then
|
||||||
rem="yes"
|
rem="yes"
|
||||||
@@ -74,14 +89,15 @@ size_class() {
|
|||||||
else
|
else
|
||||||
lg_delta_lookup="no"
|
lg_delta_lookup="no"
|
||||||
fi
|
fi
|
||||||
printf ' SC(%3d, %6d, %8d, %6d, %3s, %2s) \\\n' ${index} ${lg_grp} ${lg_delta} ${ndelta} ${bin} ${lg_delta_lookup}
|
printf ' SC(%3d, %6d, %8d, %6d, %3s, %3s, %2s) \\\n' ${index} ${lg_grp} ${lg_delta} ${ndelta} ${psz} ${bin} ${lg_delta_lookup}
|
||||||
# Defined upon return:
|
# Defined upon return:
|
||||||
# - lg_delta_lookup (${lg_delta} or "no")
|
# - psz ("yes" or "no")
|
||||||
# - bin ("yes" or "no")
|
# - bin ("yes" or "no")
|
||||||
|
# - lg_delta_lookup (${lg_delta} or "no")
|
||||||
}
|
}
|
||||||
|
|
||||||
sep_line() {
|
sep_line() {
|
||||||
echo " \\"
|
echo " \\"
|
||||||
}
|
}
|
||||||
|
|
||||||
size_classes() {
|
size_classes() {
|
||||||
@@ -95,12 +111,13 @@ size_classes() {
|
|||||||
pow2 ${lg_g}; g=${pow2_result}
|
pow2 ${lg_g}; g=${pow2_result}
|
||||||
|
|
||||||
echo "#define SIZE_CLASSES \\"
|
echo "#define SIZE_CLASSES \\"
|
||||||
echo " /* index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup */ \\"
|
echo " /* index, lg_grp, lg_delta, ndelta, psz, bin, lg_delta_lookup */ \\"
|
||||||
|
|
||||||
ntbins=0
|
ntbins=0
|
||||||
nlbins=0
|
nlbins=0
|
||||||
lg_tiny_maxclass='"NA"'
|
lg_tiny_maxclass='"NA"'
|
||||||
nbins=0
|
nbins=0
|
||||||
|
npsizes=0
|
||||||
|
|
||||||
# Tiny size classes.
|
# Tiny size classes.
|
||||||
ndelta=0
|
ndelta=0
|
||||||
@@ -112,6 +129,9 @@ size_classes() {
|
|||||||
if [ ${lg_delta_lookup} != "no" ] ; then
|
if [ ${lg_delta_lookup} != "no" ] ; then
|
||||||
nlbins=$((${index} + 1))
|
nlbins=$((${index} + 1))
|
||||||
fi
|
fi
|
||||||
|
if [ ${psz} = "yes" ] ; then
|
||||||
|
npsizes=$((${npsizes} + 1))
|
||||||
|
fi
|
||||||
if [ ${bin} != "no" ] ; then
|
if [ ${bin} != "no" ] ; then
|
||||||
nbins=$((${index} + 1))
|
nbins=$((${index} + 1))
|
||||||
fi
|
fi
|
||||||
@@ -133,11 +153,17 @@ size_classes() {
|
|||||||
index=$((${index} + 1))
|
index=$((${index} + 1))
|
||||||
lg_grp=$((${lg_grp} + 1))
|
lg_grp=$((${lg_grp} + 1))
|
||||||
lg_delta=$((${lg_delta} + 1))
|
lg_delta=$((${lg_delta} + 1))
|
||||||
|
if [ ${psz} = "yes" ] ; then
|
||||||
|
npsizes=$((${npsizes} + 1))
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
while [ ${ndelta} -lt ${g} ] ; do
|
while [ ${ndelta} -lt ${g} ] ; do
|
||||||
size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax}
|
size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax}
|
||||||
index=$((${index} + 1))
|
index=$((${index} + 1))
|
||||||
ndelta=$((${ndelta} + 1))
|
ndelta=$((${ndelta} + 1))
|
||||||
|
if [ ${psz} = "yes" ] ; then
|
||||||
|
npsizes=$((${npsizes} + 1))
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# All remaining groups.
|
# All remaining groups.
|
||||||
@@ -157,6 +183,9 @@ size_classes() {
|
|||||||
# Final written value is correct:
|
# Final written value is correct:
|
||||||
lookup_maxclass="((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))"
|
lookup_maxclass="((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))"
|
||||||
fi
|
fi
|
||||||
|
if [ ${psz} = "yes" ] ; then
|
||||||
|
npsizes=$((${npsizes} + 1))
|
||||||
|
fi
|
||||||
if [ ${bin} != "no" ] ; then
|
if [ ${bin} != "no" ] ; then
|
||||||
nbins=$((${index} + 1))
|
nbins=$((${index} + 1))
|
||||||
# Final written value is correct:
|
# Final written value is correct:
|
||||||
@@ -183,6 +212,7 @@ size_classes() {
|
|||||||
# - nlbins
|
# - nlbins
|
||||||
# - nbins
|
# - nbins
|
||||||
# - nsizes
|
# - nsizes
|
||||||
|
# - npsizes
|
||||||
# - lg_tiny_maxclass
|
# - lg_tiny_maxclass
|
||||||
# - lookup_maxclass
|
# - lookup_maxclass
|
||||||
# - small_maxclass
|
# - small_maxclass
|
||||||
@@ -200,13 +230,13 @@ cat <<EOF
|
|||||||
* be defined prior to inclusion, and it in turn defines:
|
* be defined prior to inclusion, and it in turn defines:
|
||||||
*
|
*
|
||||||
* LG_SIZE_CLASS_GROUP: Lg of size class count for each size doubling.
|
* LG_SIZE_CLASS_GROUP: Lg of size class count for each size doubling.
|
||||||
* SIZE_CLASSES: Complete table of
|
* SIZE_CLASSES: Complete table of SC(index, lg_grp, lg_delta, ndelta, psz,
|
||||||
* SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)
|
* bin, lg_delta_lookup) tuples.
|
||||||
* tuples.
|
|
||||||
* index: Size class index.
|
* index: Size class index.
|
||||||
* lg_grp: Lg group base size (no deltas added).
|
* lg_grp: Lg group base size (no deltas added).
|
||||||
* lg_delta: Lg delta to previous size class.
|
* lg_delta: Lg delta to previous size class.
|
||||||
* ndelta: Delta multiplier. size == 1<<lg_grp + ndelta<<lg_delta
|
* ndelta: Delta multiplier. size == 1<<lg_grp + ndelta<<lg_delta
|
||||||
|
* psz: 'yes' if a multiple of the page size, 'no' otherwise.
|
||||||
* bin: 'yes' if a small bin size class, 'no' otherwise.
|
* bin: 'yes' if a small bin size class, 'no' otherwise.
|
||||||
* lg_delta_lookup: Same as lg_delta if a lookup table size class, 'no'
|
* lg_delta_lookup: Same as lg_delta if a lookup table size class, 'no'
|
||||||
* otherwise.
|
* otherwise.
|
||||||
@@ -214,6 +244,7 @@ cat <<EOF
|
|||||||
* NLBINS: Number of bins supported by the lookup table.
|
* NLBINS: Number of bins supported by the lookup table.
|
||||||
* NBINS: Number of small size class bins.
|
* NBINS: Number of small size class bins.
|
||||||
* NSIZES: Number of size classes.
|
* NSIZES: Number of size classes.
|
||||||
|
* NPSIZES: Number of size classes that are a multiple of (1U << LG_PAGE).
|
||||||
* LG_TINY_MAXCLASS: Lg of maximum tiny size class.
|
* LG_TINY_MAXCLASS: Lg of maximum tiny size class.
|
||||||
* LOOKUP_MAXCLASS: Maximum size class included in lookup table.
|
* LOOKUP_MAXCLASS: Maximum size class included in lookup table.
|
||||||
* SMALL_MAXCLASS: Maximum small size class.
|
* SMALL_MAXCLASS: Maximum small size class.
|
||||||
@@ -238,6 +269,7 @@ for lg_z in ${lg_zarr} ; do
|
|||||||
echo "#define NLBINS ${nlbins}"
|
echo "#define NLBINS ${nlbins}"
|
||||||
echo "#define NBINS ${nbins}"
|
echo "#define NBINS ${nbins}"
|
||||||
echo "#define NSIZES ${nsizes}"
|
echo "#define NSIZES ${nsizes}"
|
||||||
|
echo "#define NPSIZES ${npsizes}"
|
||||||
echo "#define LG_TINY_MAXCLASS ${lg_tiny_maxclass}"
|
echo "#define LG_TINY_MAXCLASS ${lg_tiny_maxclass}"
|
||||||
echo "#define LOOKUP_MAXCLASS ${lookup_maxclass}"
|
echo "#define LOOKUP_MAXCLASS ${lookup_maxclass}"
|
||||||
echo "#define SMALL_MAXCLASS ${small_maxclass}"
|
echo "#define SMALL_MAXCLASS ${small_maxclass}"
|
||||||
|
|||||||
51
include/jemalloc/internal/spin.h
Normal file
51
include/jemalloc/internal/spin.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
#ifdef JEMALLOC_H_TYPES
|
||||||
|
|
||||||
|
typedef struct spin_s spin_t;
|
||||||
|
|
||||||
|
#endif /* JEMALLOC_H_TYPES */
|
||||||
|
/******************************************************************************/
|
||||||
|
#ifdef JEMALLOC_H_STRUCTS
|
||||||
|
|
||||||
|
struct spin_s {
|
||||||
|
unsigned iteration;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* JEMALLOC_H_STRUCTS */
|
||||||
|
/******************************************************************************/
|
||||||
|
#ifdef JEMALLOC_H_EXTERNS
|
||||||
|
|
||||||
|
#endif /* JEMALLOC_H_EXTERNS */
|
||||||
|
/******************************************************************************/
|
||||||
|
#ifdef JEMALLOC_H_INLINES
|
||||||
|
|
||||||
|
#ifndef JEMALLOC_ENABLE_INLINE
|
||||||
|
void spin_init(spin_t *spin);
|
||||||
|
void spin_adaptive(spin_t *spin);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_SPIN_C_))
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
spin_init(spin_t *spin)
|
||||||
|
{
|
||||||
|
|
||||||
|
spin->iteration = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
spin_adaptive(spin_t *spin)
|
||||||
|
{
|
||||||
|
volatile uint64_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < (KQU(1) << spin->iteration); i++)
|
||||||
|
CPU_SPINWAIT;
|
||||||
|
|
||||||
|
if (spin->iteration < 63)
|
||||||
|
spin->iteration++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* JEMALLOC_H_INLINES */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
@@ -175,25 +175,21 @@ stats_cactive_get(void)
|
|||||||
JEMALLOC_INLINE void
|
JEMALLOC_INLINE void
|
||||||
stats_cactive_add(size_t size)
|
stats_cactive_add(size_t size)
|
||||||
{
|
{
|
||||||
UNUSED size_t cactive;
|
|
||||||
|
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
assert((size & chunksize_mask) == 0);
|
assert((size & chunksize_mask) == 0);
|
||||||
|
|
||||||
cactive = atomic_add_z(&stats_cactive, size);
|
atomic_add_z(&stats_cactive, size);
|
||||||
assert(cactive - size < cactive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_INLINE void
|
JEMALLOC_INLINE void
|
||||||
stats_cactive_sub(size_t size)
|
stats_cactive_sub(size_t size)
|
||||||
{
|
{
|
||||||
UNUSED size_t cactive;
|
|
||||||
|
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
assert((size & chunksize_mask) == 0);
|
assert((size & chunksize_mask) == 0);
|
||||||
|
|
||||||
cactive = atomic_sub_z(&stats_cactive, size);
|
atomic_sub_z(&stats_cactive, size);
|
||||||
assert(cactive + size > cactive);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ tcache_t *tcache_create(tsdn_t *tsdn, arena_t *arena);
|
|||||||
void tcache_cleanup(tsd_t *tsd);
|
void tcache_cleanup(tsd_t *tsd);
|
||||||
void tcache_enabled_cleanup(tsd_t *tsd);
|
void tcache_enabled_cleanup(tsd_t *tsd);
|
||||||
void tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena);
|
void tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena);
|
||||||
bool tcaches_create(tsdn_t *tsdn, unsigned *r_ind);
|
bool tcaches_create(tsd_t *tsd, unsigned *r_ind);
|
||||||
void tcaches_flush(tsd_t *tsd, unsigned ind);
|
void tcaches_flush(tsd_t *tsd, unsigned ind);
|
||||||
void tcaches_destroy(tsd_t *tsd, unsigned ind);
|
void tcaches_destroy(tsd_t *tsd, unsigned ind);
|
||||||
bool tcache_boot(tsdn_t *tsdn);
|
bool tcache_boot(tsdn_t *tsdn);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ typedef enum {
|
|||||||
*
|
*
|
||||||
* bool example_tsd_boot(void) {...}
|
* bool example_tsd_boot(void) {...}
|
||||||
* bool example_tsd_booted_get(void) {...}
|
* bool example_tsd_booted_get(void) {...}
|
||||||
* example_t *example_tsd_get() {...}
|
* example_t *example_tsd_get(bool init) {...}
|
||||||
* void example_tsd_set(example_t *val) {...}
|
* void example_tsd_set(example_t *val) {...}
|
||||||
*
|
*
|
||||||
* Note that all of the functions deal in terms of (a_type *) rather than
|
* Note that all of the functions deal in terms of (a_type *) rather than
|
||||||
@@ -105,7 +105,7 @@ a_name##tsd_boot(void); \
|
|||||||
a_attr bool \
|
a_attr bool \
|
||||||
a_name##tsd_booted_get(void); \
|
a_name##tsd_booted_get(void); \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_name##tsd_get(void); \
|
a_name##tsd_get(bool init); \
|
||||||
a_attr void \
|
a_attr void \
|
||||||
a_name##tsd_set(a_type *val);
|
a_name##tsd_set(a_type *val);
|
||||||
|
|
||||||
@@ -213,9 +213,15 @@ a_name##tsd_booted_get(void) \
|
|||||||
\
|
\
|
||||||
return (a_name##tsd_booted); \
|
return (a_name##tsd_booted); \
|
||||||
} \
|
} \
|
||||||
|
a_attr bool \
|
||||||
|
a_name##tsd_get_allocates(void) \
|
||||||
|
{ \
|
||||||
|
\
|
||||||
|
return (false); \
|
||||||
|
} \
|
||||||
/* Get/set. */ \
|
/* Get/set. */ \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_name##tsd_get(void) \
|
a_name##tsd_get(bool init) \
|
||||||
{ \
|
{ \
|
||||||
\
|
\
|
||||||
assert(a_name##tsd_booted); \
|
assert(a_name##tsd_booted); \
|
||||||
@@ -264,9 +270,15 @@ a_name##tsd_booted_get(void) \
|
|||||||
\
|
\
|
||||||
return (a_name##tsd_booted); \
|
return (a_name##tsd_booted); \
|
||||||
} \
|
} \
|
||||||
|
a_attr bool \
|
||||||
|
a_name##tsd_get_allocates(void) \
|
||||||
|
{ \
|
||||||
|
\
|
||||||
|
return (false); \
|
||||||
|
} \
|
||||||
/* Get/set. */ \
|
/* Get/set. */ \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_name##tsd_get(void) \
|
a_name##tsd_get(bool init) \
|
||||||
{ \
|
{ \
|
||||||
\
|
\
|
||||||
assert(a_name##tsd_booted); \
|
assert(a_name##tsd_booted); \
|
||||||
@@ -325,14 +337,14 @@ a_name##tsd_wrapper_set(a_name##tsd_wrapper_t *wrapper) \
|
|||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
a_attr a_name##tsd_wrapper_t * \
|
a_attr a_name##tsd_wrapper_t * \
|
||||||
a_name##tsd_wrapper_get(void) \
|
a_name##tsd_wrapper_get(bool init) \
|
||||||
{ \
|
{ \
|
||||||
DWORD error = GetLastError(); \
|
DWORD error = GetLastError(); \
|
||||||
a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *) \
|
a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *) \
|
||||||
TlsGetValue(a_name##tsd_tsd); \
|
TlsGetValue(a_name##tsd_tsd); \
|
||||||
SetLastError(error); \
|
SetLastError(error); \
|
||||||
\
|
\
|
||||||
if (unlikely(wrapper == NULL)) { \
|
if (init && unlikely(wrapper == NULL)) { \
|
||||||
wrapper = (a_name##tsd_wrapper_t *) \
|
wrapper = (a_name##tsd_wrapper_t *) \
|
||||||
malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t)); \
|
malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t)); \
|
||||||
if (wrapper == NULL) { \
|
if (wrapper == NULL) { \
|
||||||
@@ -392,14 +404,22 @@ a_name##tsd_booted_get(void) \
|
|||||||
\
|
\
|
||||||
return (a_name##tsd_booted); \
|
return (a_name##tsd_booted); \
|
||||||
} \
|
} \
|
||||||
|
a_attr bool \
|
||||||
|
a_name##tsd_get_allocates(void) \
|
||||||
|
{ \
|
||||||
|
\
|
||||||
|
return (true); \
|
||||||
|
} \
|
||||||
/* Get/set. */ \
|
/* Get/set. */ \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_name##tsd_get(void) \
|
a_name##tsd_get(bool init) \
|
||||||
{ \
|
{ \
|
||||||
a_name##tsd_wrapper_t *wrapper; \
|
a_name##tsd_wrapper_t *wrapper; \
|
||||||
\
|
\
|
||||||
assert(a_name##tsd_booted); \
|
assert(a_name##tsd_booted); \
|
||||||
wrapper = a_name##tsd_wrapper_get(); \
|
wrapper = a_name##tsd_wrapper_get(init); \
|
||||||
|
if (a_name##tsd_get_allocates() && !init && wrapper == NULL) \
|
||||||
|
return (NULL); \
|
||||||
return (&wrapper->val); \
|
return (&wrapper->val); \
|
||||||
} \
|
} \
|
||||||
a_attr void \
|
a_attr void \
|
||||||
@@ -408,7 +428,7 @@ a_name##tsd_set(a_type *val) \
|
|||||||
a_name##tsd_wrapper_t *wrapper; \
|
a_name##tsd_wrapper_t *wrapper; \
|
||||||
\
|
\
|
||||||
assert(a_name##tsd_booted); \
|
assert(a_name##tsd_booted); \
|
||||||
wrapper = a_name##tsd_wrapper_get(); \
|
wrapper = a_name##tsd_wrapper_get(true); \
|
||||||
wrapper->val = *(val); \
|
wrapper->val = *(val); \
|
||||||
if (a_cleanup != malloc_tsd_no_cleanup) \
|
if (a_cleanup != malloc_tsd_no_cleanup) \
|
||||||
wrapper->initialized = true; \
|
wrapper->initialized = true; \
|
||||||
@@ -452,12 +472,12 @@ a_name##tsd_wrapper_set(a_name##tsd_wrapper_t *wrapper) \
|
|||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
a_attr a_name##tsd_wrapper_t * \
|
a_attr a_name##tsd_wrapper_t * \
|
||||||
a_name##tsd_wrapper_get(void) \
|
a_name##tsd_wrapper_get(bool init) \
|
||||||
{ \
|
{ \
|
||||||
a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *) \
|
a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *) \
|
||||||
pthread_getspecific(a_name##tsd_tsd); \
|
pthread_getspecific(a_name##tsd_tsd); \
|
||||||
\
|
\
|
||||||
if (unlikely(wrapper == NULL)) { \
|
if (init && unlikely(wrapper == NULL)) { \
|
||||||
tsd_init_block_t block; \
|
tsd_init_block_t block; \
|
||||||
wrapper = tsd_init_check_recursion( \
|
wrapper = tsd_init_check_recursion( \
|
||||||
&a_name##tsd_init_head, &block); \
|
&a_name##tsd_init_head, &block); \
|
||||||
@@ -520,14 +540,22 @@ a_name##tsd_booted_get(void) \
|
|||||||
\
|
\
|
||||||
return (a_name##tsd_booted); \
|
return (a_name##tsd_booted); \
|
||||||
} \
|
} \
|
||||||
|
a_attr bool \
|
||||||
|
a_name##tsd_get_allocates(void) \
|
||||||
|
{ \
|
||||||
|
\
|
||||||
|
return (true); \
|
||||||
|
} \
|
||||||
/* Get/set. */ \
|
/* Get/set. */ \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_name##tsd_get(void) \
|
a_name##tsd_get(bool init) \
|
||||||
{ \
|
{ \
|
||||||
a_name##tsd_wrapper_t *wrapper; \
|
a_name##tsd_wrapper_t *wrapper; \
|
||||||
\
|
\
|
||||||
assert(a_name##tsd_booted); \
|
assert(a_name##tsd_booted); \
|
||||||
wrapper = a_name##tsd_wrapper_get(); \
|
wrapper = a_name##tsd_wrapper_get(init); \
|
||||||
|
if (a_name##tsd_get_allocates() && !init && wrapper == NULL) \
|
||||||
|
return (NULL); \
|
||||||
return (&wrapper->val); \
|
return (&wrapper->val); \
|
||||||
} \
|
} \
|
||||||
a_attr void \
|
a_attr void \
|
||||||
@@ -536,7 +564,7 @@ a_name##tsd_set(a_type *val) \
|
|||||||
a_name##tsd_wrapper_t *wrapper; \
|
a_name##tsd_wrapper_t *wrapper; \
|
||||||
\
|
\
|
||||||
assert(a_name##tsd_booted); \
|
assert(a_name##tsd_booted); \
|
||||||
wrapper = a_name##tsd_wrapper_get(); \
|
wrapper = a_name##tsd_wrapper_get(true); \
|
||||||
wrapper->val = *(val); \
|
wrapper->val = *(val); \
|
||||||
if (a_cleanup != malloc_tsd_no_cleanup) \
|
if (a_cleanup != malloc_tsd_no_cleanup) \
|
||||||
wrapper->initialized = true; \
|
wrapper->initialized = true; \
|
||||||
@@ -639,6 +667,7 @@ void tsd_cleanup(void *arg);
|
|||||||
#ifndef JEMALLOC_ENABLE_INLINE
|
#ifndef JEMALLOC_ENABLE_INLINE
|
||||||
malloc_tsd_protos(JEMALLOC_ATTR(unused), , tsd_t)
|
malloc_tsd_protos(JEMALLOC_ATTR(unused), , tsd_t)
|
||||||
|
|
||||||
|
tsd_t *tsd_fetch_impl(bool init);
|
||||||
tsd_t *tsd_fetch(void);
|
tsd_t *tsd_fetch(void);
|
||||||
tsdn_t *tsd_tsdn(tsd_t *tsd);
|
tsdn_t *tsd_tsdn(tsd_t *tsd);
|
||||||
bool tsd_nominal(tsd_t *tsd);
|
bool tsd_nominal(tsd_t *tsd);
|
||||||
@@ -658,9 +687,13 @@ malloc_tsd_externs(, tsd_t)
|
|||||||
malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, , tsd_t, tsd_initializer, tsd_cleanup)
|
malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, , tsd_t, tsd_initializer, tsd_cleanup)
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE tsd_t *
|
JEMALLOC_ALWAYS_INLINE tsd_t *
|
||||||
tsd_fetch(void)
|
tsd_fetch_impl(bool init)
|
||||||
{
|
{
|
||||||
tsd_t *tsd = tsd_get();
|
tsd_t *tsd = tsd_get(init);
|
||||||
|
|
||||||
|
if (!init && tsd_get_allocates() && tsd == NULL)
|
||||||
|
return (NULL);
|
||||||
|
assert(tsd != NULL);
|
||||||
|
|
||||||
if (unlikely(tsd->state != tsd_state_nominal)) {
|
if (unlikely(tsd->state != tsd_state_nominal)) {
|
||||||
if (tsd->state == tsd_state_uninitialized) {
|
if (tsd->state == tsd_state_uninitialized) {
|
||||||
@@ -677,6 +710,13 @@ tsd_fetch(void)
|
|||||||
return (tsd);
|
return (tsd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JEMALLOC_ALWAYS_INLINE tsd_t *
|
||||||
|
tsd_fetch(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (tsd_fetch_impl(true));
|
||||||
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE tsdn_t *
|
JEMALLOC_ALWAYS_INLINE tsdn_t *
|
||||||
tsd_tsdn(tsd_t *tsd)
|
tsd_tsdn(tsd_t *tsd)
|
||||||
{
|
{
|
||||||
@@ -723,7 +763,7 @@ tsdn_fetch(void)
|
|||||||
if (!tsd_booted_get())
|
if (!tsd_booted_get())
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
return (tsd_tsdn(tsd_fetch()));
|
return (tsd_tsdn(tsd_fetch_impl(false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE bool
|
JEMALLOC_ALWAYS_INLINE bool
|
||||||
|
|||||||
@@ -41,8 +41,12 @@
|
|||||||
#define MALLOC_PRINTF_BUFSIZE 4096
|
#define MALLOC_PRINTF_BUFSIZE 4096
|
||||||
|
|
||||||
/* Junk fill patterns. */
|
/* Junk fill patterns. */
|
||||||
#define JEMALLOC_ALLOC_JUNK ((uint8_t)0xa5)
|
#ifndef JEMALLOC_ALLOC_JUNK
|
||||||
#define JEMALLOC_FREE_JUNK ((uint8_t)0x5a)
|
# define JEMALLOC_ALLOC_JUNK ((uint8_t)0xa5)
|
||||||
|
#endif
|
||||||
|
#ifndef JEMALLOC_FREE_JUNK
|
||||||
|
# define JEMALLOC_FREE_JUNK ((uint8_t)0x5a)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrap a cpp argument that contains commas such that it isn't broken up into
|
* Wrap a cpp argument that contains commas such that it isn't broken up into
|
||||||
@@ -61,30 +65,20 @@
|
|||||||
# define JEMALLOC_CC_SILENCE_INIT(v)
|
# define JEMALLOC_CC_SILENCE_INIT(v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define JEMALLOC_GNUC_PREREQ(major, minor) \
|
|
||||||
(!defined(__clang__) && \
|
|
||||||
(__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))))
|
|
||||||
#ifndef __has_builtin
|
|
||||||
# define __has_builtin(builtin) (0)
|
|
||||||
#endif
|
|
||||||
#define JEMALLOC_CLANG_HAS_BUILTIN(builtin) \
|
|
||||||
(defined(__clang__) && __has_builtin(builtin))
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# define likely(x) __builtin_expect(!!(x), 1)
|
# define likely(x) __builtin_expect(!!(x), 1)
|
||||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
# define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
# if JEMALLOC_GNUC_PREREQ(4, 6) || \
|
|
||||||
JEMALLOC_CLANG_HAS_BUILTIN(__builtin_unreachable)
|
|
||||||
# define unreachable() __builtin_unreachable()
|
|
||||||
# else
|
|
||||||
# define unreachable() abort()
|
|
||||||
# endif
|
|
||||||
#else
|
#else
|
||||||
# define likely(x) !!(x)
|
# define likely(x) !!(x)
|
||||||
# define unlikely(x) !!(x)
|
# define unlikely(x) !!(x)
|
||||||
# define unreachable() abort()
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(JEMALLOC_INTERNAL_UNREACHABLE)
|
||||||
|
# error JEMALLOC_INTERNAL_UNREACHABLE should have been defined by configure
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define unreachable() JEMALLOC_INTERNAL_UNREACHABLE()
|
||||||
|
|
||||||
#include "jemalloc/internal/assert.h"
|
#include "jemalloc/internal/assert.h"
|
||||||
|
|
||||||
/* Use to assert a particular configuration, e.g., cassert(config_debug). */
|
/* Use to assert a particular configuration, e.g., cassert(config_debug). */
|
||||||
|
|||||||
@@ -36,13 +36,25 @@
|
|||||||
zero); \
|
zero); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define JEMALLOC_VALGRIND_REALLOC(maybe_moved, tsdn, ptr, usize, \
|
#define JEMALLOC_VALGRIND_REALLOC_MOVED_no(ptr, old_ptr) \
|
||||||
ptr_maybe_null, old_ptr, old_usize, old_rzsize, old_ptr_maybe_null, \
|
(false)
|
||||||
zero) do { \
|
#define JEMALLOC_VALGRIND_REALLOC_MOVED_maybe(ptr, old_ptr) \
|
||||||
|
((ptr) != (old_ptr))
|
||||||
|
#define JEMALLOC_VALGRIND_REALLOC_PTR_NULL_no(ptr) \
|
||||||
|
(false)
|
||||||
|
#define JEMALLOC_VALGRIND_REALLOC_PTR_NULL_maybe(ptr) \
|
||||||
|
(ptr == NULL)
|
||||||
|
#define JEMALLOC_VALGRIND_REALLOC_OLD_PTR_NULL_no(old_ptr) \
|
||||||
|
(false)
|
||||||
|
#define JEMALLOC_VALGRIND_REALLOC_OLD_PTR_NULL_maybe(old_ptr) \
|
||||||
|
(old_ptr == NULL)
|
||||||
|
#define JEMALLOC_VALGRIND_REALLOC(moved, tsdn, ptr, usize, ptr_null, \
|
||||||
|
old_ptr, old_usize, old_rzsize, old_ptr_null, zero) do { \
|
||||||
if (unlikely(in_valgrind)) { \
|
if (unlikely(in_valgrind)) { \
|
||||||
size_t rzsize = p2rz(tsdn, ptr); \
|
size_t rzsize = p2rz(tsdn, ptr); \
|
||||||
\
|
\
|
||||||
if (!maybe_moved || ptr == old_ptr) { \
|
if (!JEMALLOC_VALGRIND_REALLOC_MOVED_##moved(ptr, \
|
||||||
|
old_ptr)) { \
|
||||||
VALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize, \
|
VALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize, \
|
||||||
usize, rzsize); \
|
usize, rzsize); \
|
||||||
if (zero && old_usize < usize) { \
|
if (zero && old_usize < usize) { \
|
||||||
@@ -51,11 +63,13 @@
|
|||||||
old_usize), usize - old_usize); \
|
old_usize), usize - old_usize); \
|
||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
if (!old_ptr_maybe_null || old_ptr != NULL) { \
|
if (!JEMALLOC_VALGRIND_REALLOC_OLD_PTR_NULL_## \
|
||||||
|
old_ptr_null(old_ptr)) { \
|
||||||
valgrind_freelike_block(old_ptr, \
|
valgrind_freelike_block(old_ptr, \
|
||||||
old_rzsize); \
|
old_rzsize); \
|
||||||
} \
|
} \
|
||||||
if (!ptr_maybe_null || ptr != NULL) { \
|
if (!JEMALLOC_VALGRIND_REALLOC_PTR_NULL_## \
|
||||||
|
ptr_null(ptr)) { \
|
||||||
size_t copy_size = (old_usize < usize) \
|
size_t copy_size = (old_usize < usize) \
|
||||||
? old_usize : usize; \
|
? old_usize : usize; \
|
||||||
size_t tail_size = usize - copy_size; \
|
size_t tail_size = usize - copy_size; \
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ void witness_postfork_child(tsd_t *tsd);
|
|||||||
#ifdef JEMALLOC_H_INLINES
|
#ifdef JEMALLOC_H_INLINES
|
||||||
|
|
||||||
#ifndef JEMALLOC_ENABLE_INLINE
|
#ifndef JEMALLOC_ENABLE_INLINE
|
||||||
|
bool witness_owner(tsd_t *tsd, const witness_t *witness);
|
||||||
void witness_assert_owner(tsdn_t *tsdn, const witness_t *witness);
|
void witness_assert_owner(tsdn_t *tsdn, const witness_t *witness);
|
||||||
void witness_assert_not_owner(tsdn_t *tsdn, const witness_t *witness);
|
void witness_assert_not_owner(tsdn_t *tsdn, const witness_t *witness);
|
||||||
void witness_assert_lockless(tsdn_t *tsdn);
|
void witness_assert_lockless(tsdn_t *tsdn);
|
||||||
@@ -116,12 +117,25 @@ void witness_unlock(tsdn_t *tsdn, witness_t *witness);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))
|
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
witness_owner(tsd_t *tsd, const witness_t *witness)
|
||||||
|
{
|
||||||
|
witness_list_t *witnesses;
|
||||||
|
witness_t *w;
|
||||||
|
|
||||||
|
witnesses = tsd_witnessesp_get(tsd);
|
||||||
|
ql_foreach(w, witnesses, link) {
|
||||||
|
if (w == witness)
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
JEMALLOC_INLINE void
|
JEMALLOC_INLINE void
|
||||||
witness_assert_owner(tsdn_t *tsdn, const witness_t *witness)
|
witness_assert_owner(tsdn_t *tsdn, const witness_t *witness)
|
||||||
{
|
{
|
||||||
tsd_t *tsd;
|
tsd_t *tsd;
|
||||||
witness_list_t *witnesses;
|
|
||||||
witness_t *w;
|
|
||||||
|
|
||||||
if (!config_debug)
|
if (!config_debug)
|
||||||
return;
|
return;
|
||||||
@@ -132,11 +146,8 @@ witness_assert_owner(tsdn_t *tsdn, const witness_t *witness)
|
|||||||
if (witness->rank == WITNESS_RANK_OMIT)
|
if (witness->rank == WITNESS_RANK_OMIT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
witnesses = tsd_witnessesp_get(tsd);
|
if (witness_owner(tsd, witness))
|
||||||
ql_foreach(w, witnesses, link) {
|
return;
|
||||||
if (w == witness)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
witness_owner_error(witness);
|
witness_owner_error(witness);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,10 +249,16 @@ witness_unlock(tsdn_t *tsdn, witness_t *witness)
|
|||||||
if (witness->rank == WITNESS_RANK_OMIT)
|
if (witness->rank == WITNESS_RANK_OMIT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
witness_assert_owner(tsdn, witness);
|
/*
|
||||||
|
* Check whether owner before removal, rather than relying on
|
||||||
witnesses = tsd_witnessesp_get(tsd);
|
* witness_assert_owner() to abort, so that unit tests can test this
|
||||||
ql_remove(witnesses, witness, link);
|
* function's failure mode without causing undefined behavior.
|
||||||
|
*/
|
||||||
|
if (witness_owner(tsd, witness)) {
|
||||||
|
witnesses = tsd_witnessesp_get(tsd);
|
||||||
|
ql_remove(witnesses, witness, link);
|
||||||
|
} else
|
||||||
|
witness_assert_owner(tsdn, witness);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ install_suffix=@install_suffix@
|
|||||||
|
|
||||||
Name: jemalloc
|
Name: jemalloc
|
||||||
Description: A general purpose malloc(3) implementation that emphasizes fragmentation avoidance and scalable concurrency support.
|
Description: A general purpose malloc(3) implementation that emphasizes fragmentation avoidance and scalable concurrency support.
|
||||||
URL: http://www.canonware.com/jemalloc
|
URL: http://jemalloc.net/
|
||||||
Version: @jemalloc_version@
|
Version: @jemalloc_version@
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
Libs: -L${libdir} -ljemalloc${install_suffix}
|
Libs: -L${libdir} -ljemalloc${install_suffix}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ How to build jemalloc for Windows
|
|||||||
(note: x86/x64 doesn't matter at this point)
|
(note: x86/x64 doesn't matter at this point)
|
||||||
|
|
||||||
5. Generate header files:
|
5. Generate header files:
|
||||||
sh -c "./autogen.sh CC=cl --enable-lazy-lock=no"
|
sh -c "CC=cl ./autogen.sh"
|
||||||
|
|
||||||
6. Now the project can be opened and built in Visual Studio:
|
6. Now the project can be opened and built in Visual Studio:
|
||||||
msvc\jemalloc_vc2015.sln
|
msvc\jemalloc_vc2015.sln
|
||||||
|
|||||||
@@ -69,12 +69,14 @@
|
|||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\rb.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\rb.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\rtree.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\rtree.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\size_classes.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\size_classes.h" />
|
||||||
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\smoothstep.h" />
|
||||||
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\spin.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\stats.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\stats.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\tcache.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\tcache.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\ticker.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\ticker.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\tsd.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\tsd.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\util.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\util.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\valgrind.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\witness.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\jemalloc.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\jemalloc.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\jemalloc_defs.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\jemalloc_defs.h" />
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\jemalloc_macros.h" />
|
<ClInclude Include="..\..\..\..\include\jemalloc\jemalloc_macros.h" />
|
||||||
@@ -110,11 +112,13 @@
|
|||||||
<ClCompile Include="..\..\..\..\src\prof.c" />
|
<ClCompile Include="..\..\..\..\src\prof.c" />
|
||||||
<ClCompile Include="..\..\..\..\src\quarantine.c" />
|
<ClCompile Include="..\..\..\..\src\quarantine.c" />
|
||||||
<ClCompile Include="..\..\..\..\src\rtree.c" />
|
<ClCompile Include="..\..\..\..\src\rtree.c" />
|
||||||
|
<ClCompile Include="..\..\..\..\src\spin.c" />
|
||||||
<ClCompile Include="..\..\..\..\src\stats.c" />
|
<ClCompile Include="..\..\..\..\src\stats.c" />
|
||||||
<ClCompile Include="..\..\..\..\src\tcache.c" />
|
<ClCompile Include="..\..\..\..\src\tcache.c" />
|
||||||
<ClCompile Include="..\..\..\..\src\ticker.c" />
|
<ClCompile Include="..\..\..\..\src\ticker.c" />
|
||||||
<ClCompile Include="..\..\..\..\src\tsd.c" />
|
<ClCompile Include="..\..\..\..\src\tsd.c" />
|
||||||
<ClCompile Include="..\..\..\..\src\util.c" />
|
<ClCompile Include="..\..\..\..\src\util.c" />
|
||||||
|
<ClCompile Include="..\..\..\..\src\witness.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{8D6BB292-9E1C-413D-9F98-4864BDC1514A}</ProjectGuid>
|
<ProjectGuid>{8D6BB292-9E1C-413D-9F98-4864BDC1514A}</ProjectGuid>
|
||||||
|
|||||||
@@ -146,6 +146,12 @@
|
|||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\size_classes.h">
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\size_classes.h">
|
||||||
<Filter>Header Files\internal</Filter>
|
<Filter>Header Files\internal</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\smoothstep.h">
|
||||||
|
<Filter>Header Files\internal</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\spin.h">
|
||||||
|
<Filter>Header Files\internal</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\stats.h">
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\stats.h">
|
||||||
<Filter>Header Files\internal</Filter>
|
<Filter>Header Files\internal</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -161,7 +167,7 @@
|
|||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\util.h">
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\util.h">
|
||||||
<Filter>Header Files\internal</Filter>
|
<Filter>Header Files\internal</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\..\..\include\jemalloc\internal\valgrind.h">
|
<ClInclude Include="..\..\..\..\include\jemalloc\internal\witness.h">
|
||||||
<Filter>Header Files\internal</Filter>
|
<Filter>Header Files\internal</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\..\..\include\msvc_compat\strings.h">
|
<ClInclude Include="..\..\..\..\include\msvc_compat\strings.h">
|
||||||
@@ -241,6 +247,9 @@
|
|||||||
<ClCompile Include="..\..\..\..\src\rtree.c">
|
<ClCompile Include="..\..\..\..\src\rtree.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\..\src\spin.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\src\stats.c">
|
<ClCompile Include="..\..\..\..\src\stats.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -256,5 +265,8 @@
|
|||||||
<ClCompile Include="..\..\..\..\src\util.c">
|
<ClCompile Include="..\..\..\..\src\util.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\..\src\witness.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
6
msvc/projects/vc2015/test_threads/test_threads.cpp
Normal file → Executable file
6
msvc/projects/vc2015/test_threads/test_threads.cpp
Normal file → Executable file
@@ -21,7 +21,7 @@ int test_threads()
|
|||||||
je_malloc_conf = "narenas:3";
|
je_malloc_conf = "narenas:3";
|
||||||
int narenas = 0;
|
int narenas = 0;
|
||||||
size_t sz = sizeof(narenas);
|
size_t sz = sizeof(narenas);
|
||||||
je_mallctl("opt.narenas", &narenas, &sz, NULL, 0);
|
je_mallctl("opt.narenas", (void *)&narenas, &sz, NULL, 0);
|
||||||
if (narenas != 3) {
|
if (narenas != 3) {
|
||||||
printf("Error: unexpected number of arenas: %d\n", narenas);
|
printf("Error: unexpected number of arenas: %d\n", narenas);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -33,7 +33,7 @@ int test_threads()
|
|||||||
je_malloc_stats_print(NULL, NULL, NULL);
|
je_malloc_stats_print(NULL, NULL, NULL);
|
||||||
size_t allocated1;
|
size_t allocated1;
|
||||||
size_t sz1 = sizeof(allocated1);
|
size_t sz1 = sizeof(allocated1);
|
||||||
je_mallctl("stats.active", &allocated1, &sz1, NULL, 0);
|
je_mallctl("stats.active", (void *)&allocated1, &sz1, NULL, 0);
|
||||||
printf("\nPress Enter to start threads...\n");
|
printf("\nPress Enter to start threads...\n");
|
||||||
getchar();
|
getchar();
|
||||||
printf("Starting %d threads x %d x %d iterations...\n", numThreads, numIter1, numIter2);
|
printf("Starting %d threads x %d x %d iterations...\n", numThreads, numIter1, numIter2);
|
||||||
@@ -78,7 +78,7 @@ int test_threads()
|
|||||||
}
|
}
|
||||||
je_malloc_stats_print(NULL, NULL, NULL);
|
je_malloc_stats_print(NULL, NULL, NULL);
|
||||||
size_t allocated2;
|
size_t allocated2;
|
||||||
je_mallctl("stats.active", &allocated2, &sz1, NULL, 0);
|
je_mallctl("stats.active", (void *)&allocated2, &sz1, NULL, 0);
|
||||||
size_t leaked = allocated2 - allocated1;
|
size_t leaked = allocated2 - allocated1;
|
||||||
printf("\nDone. Leaked: %zd bytes\n", leaked);
|
printf("\nDone. Leaked: %zd bytes\n", leaked);
|
||||||
bool failed = leaked > 65536; // in case C++ runtime allocated something (e.g. iostream locale or facet)
|
bool failed = leaked > 65536; // in case C++ runtime allocated something (e.g. iostream locale or facet)
|
||||||
|
|||||||
598
src/arena.c
598
src/arena.c
File diff suppressed because it is too large
Load Diff
24
src/base.c
24
src/base.c
@@ -5,7 +5,8 @@
|
|||||||
/* Data. */
|
/* Data. */
|
||||||
|
|
||||||
static malloc_mutex_t base_mtx;
|
static malloc_mutex_t base_mtx;
|
||||||
static extent_tree_t base_avail_szad;
|
static size_t base_extent_sn_next;
|
||||||
|
static extent_tree_t base_avail_szsnad;
|
||||||
static extent_node_t *base_nodes;
|
static extent_node_t *base_nodes;
|
||||||
static size_t base_allocated;
|
static size_t base_allocated;
|
||||||
static size_t base_resident;
|
static size_t base_resident;
|
||||||
@@ -39,6 +40,14 @@ base_node_dalloc(tsdn_t *tsdn, extent_node_t *node)
|
|||||||
base_nodes = node;
|
base_nodes = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
base_extent_node_init(extent_node_t *node, void *addr, size_t size)
|
||||||
|
{
|
||||||
|
size_t sn = atomic_add_z(&base_extent_sn_next, 1) - 1;
|
||||||
|
|
||||||
|
extent_node_init(node, NULL, addr, size, sn, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
static extent_node_t *
|
static extent_node_t *
|
||||||
base_chunk_alloc(tsdn_t *tsdn, size_t minsize)
|
base_chunk_alloc(tsdn_t *tsdn, size_t minsize)
|
||||||
{
|
{
|
||||||
@@ -68,7 +77,7 @@ base_chunk_alloc(tsdn_t *tsdn, size_t minsize)
|
|||||||
base_resident += PAGE_CEILING(nsize);
|
base_resident += PAGE_CEILING(nsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extent_node_init(node, NULL, addr, csize, true, true);
|
base_extent_node_init(node, addr, csize);
|
||||||
return (node);
|
return (node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,12 +101,12 @@ base_alloc(tsdn_t *tsdn, size_t size)
|
|||||||
csize = CACHELINE_CEILING(size);
|
csize = CACHELINE_CEILING(size);
|
||||||
|
|
||||||
usize = s2u(csize);
|
usize = s2u(csize);
|
||||||
extent_node_init(&key, NULL, NULL, usize, false, false);
|
extent_node_init(&key, NULL, NULL, usize, 0, false, false);
|
||||||
malloc_mutex_lock(tsdn, &base_mtx);
|
malloc_mutex_lock(tsdn, &base_mtx);
|
||||||
node = extent_tree_szad_nsearch(&base_avail_szad, &key);
|
node = extent_tree_szsnad_nsearch(&base_avail_szsnad, &key);
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
/* Use existing space. */
|
/* Use existing space. */
|
||||||
extent_tree_szad_remove(&base_avail_szad, node);
|
extent_tree_szsnad_remove(&base_avail_szsnad, node);
|
||||||
} else {
|
} else {
|
||||||
/* Try to allocate more space. */
|
/* Try to allocate more space. */
|
||||||
node = base_chunk_alloc(tsdn, csize);
|
node = base_chunk_alloc(tsdn, csize);
|
||||||
@@ -111,7 +120,7 @@ base_alloc(tsdn_t *tsdn, size_t size)
|
|||||||
if (extent_node_size_get(node) > csize) {
|
if (extent_node_size_get(node) > csize) {
|
||||||
extent_node_addr_set(node, (void *)((uintptr_t)ret + csize));
|
extent_node_addr_set(node, (void *)((uintptr_t)ret + csize));
|
||||||
extent_node_size_set(node, extent_node_size_get(node) - csize);
|
extent_node_size_set(node, extent_node_size_get(node) - csize);
|
||||||
extent_tree_szad_insert(&base_avail_szad, node);
|
extent_tree_szsnad_insert(&base_avail_szsnad, node);
|
||||||
} else
|
} else
|
||||||
base_node_dalloc(tsdn, node);
|
base_node_dalloc(tsdn, node);
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
@@ -149,7 +158,8 @@ base_boot(void)
|
|||||||
|
|
||||||
if (malloc_mutex_init(&base_mtx, "base", WITNESS_RANK_BASE))
|
if (malloc_mutex_init(&base_mtx, "base", WITNESS_RANK_BASE))
|
||||||
return (true);
|
return (true);
|
||||||
extent_tree_szad_new(&base_avail_szad);
|
base_extent_sn_next = 0;
|
||||||
|
extent_tree_szsnad_new(&base_avail_szsnad);
|
||||||
base_nodes = NULL;
|
base_nodes = NULL;
|
||||||
|
|
||||||
return (false);
|
return (false);
|
||||||
|
|||||||
231
src/chunk.c
231
src/chunk.c
@@ -50,9 +50,9 @@ const chunk_hooks_t chunk_hooks_default = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static void chunk_record(tsdn_t *tsdn, arena_t *arena,
|
static void chunk_record(tsdn_t *tsdn, arena_t *arena,
|
||||||
chunk_hooks_t *chunk_hooks, extent_tree_t *chunks_szad,
|
chunk_hooks_t *chunk_hooks, extent_tree_t *chunks_szsnad,
|
||||||
extent_tree_t *chunks_ad, bool cache, void *chunk, size_t size, bool zeroed,
|
extent_tree_t *chunks_ad, bool cache, void *chunk, size_t size, size_t sn,
|
||||||
bool committed);
|
bool zeroed, bool committed);
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@@ -183,33 +183,35 @@ chunk_deregister(const void *chunk, const extent_node_t *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do first-best-fit chunk selection, i.e. select the lowest chunk that best
|
* Do first-best-fit chunk selection, i.e. select the oldest/lowest chunk that
|
||||||
* fits.
|
* best fits.
|
||||||
*/
|
*/
|
||||||
static extent_node_t *
|
static extent_node_t *
|
||||||
chunk_first_best_fit(arena_t *arena, extent_tree_t *chunks_szad,
|
chunk_first_best_fit(arena_t *arena, extent_tree_t *chunks_szsnad, size_t size)
|
||||||
extent_tree_t *chunks_ad, size_t size)
|
|
||||||
{
|
{
|
||||||
extent_node_t key;
|
extent_node_t key;
|
||||||
|
|
||||||
assert(size == CHUNK_CEILING(size));
|
assert(size == CHUNK_CEILING(size));
|
||||||
|
|
||||||
extent_node_init(&key, arena, NULL, size, false, false);
|
extent_node_init(&key, arena, NULL, size, 0, false, false);
|
||||||
return (extent_tree_szad_nsearch(chunks_szad, &key));
|
return (extent_tree_szsnad_nsearch(chunks_szsnad, &key));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
||||||
extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, bool cache,
|
extent_tree_t *chunks_szsnad, extent_tree_t *chunks_ad, bool cache,
|
||||||
void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit,
|
void *new_addr, size_t size, size_t alignment, size_t *sn, bool *zero,
|
||||||
bool dalloc_node)
|
bool *commit, bool dalloc_node)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
extent_node_t *node;
|
extent_node_t *node;
|
||||||
size_t alloc_size, leadsize, trailsize;
|
size_t alloc_size, leadsize, trailsize;
|
||||||
bool zeroed, committed;
|
bool zeroed, committed;
|
||||||
|
|
||||||
|
assert(CHUNK_CEILING(size) == size);
|
||||||
|
assert(alignment > 0);
|
||||||
assert(new_addr == NULL || alignment == chunksize);
|
assert(new_addr == NULL || alignment == chunksize);
|
||||||
|
assert(CHUNK_ADDR2BASE(new_addr) == new_addr);
|
||||||
/*
|
/*
|
||||||
* Cached chunks use the node linkage embedded in their headers, in
|
* Cached chunks use the node linkage embedded in their headers, in
|
||||||
* which case dalloc_node is true, and new_addr is non-NULL because
|
* which case dalloc_node is true, and new_addr is non-NULL because
|
||||||
@@ -217,7 +219,7 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
*/
|
*/
|
||||||
assert(dalloc_node || new_addr != NULL);
|
assert(dalloc_node || new_addr != NULL);
|
||||||
|
|
||||||
alloc_size = CHUNK_CEILING(s2u(size + alignment - chunksize));
|
alloc_size = size + CHUNK_CEILING(alignment) - chunksize;
|
||||||
/* Beware size_t wrap-around. */
|
/* Beware size_t wrap-around. */
|
||||||
if (alloc_size < size)
|
if (alloc_size < size)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -225,12 +227,11 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
chunk_hooks_assure_initialized_locked(tsdn, arena, chunk_hooks);
|
chunk_hooks_assure_initialized_locked(tsdn, arena, chunk_hooks);
|
||||||
if (new_addr != NULL) {
|
if (new_addr != NULL) {
|
||||||
extent_node_t key;
|
extent_node_t key;
|
||||||
extent_node_init(&key, arena, new_addr, alloc_size, false,
|
extent_node_init(&key, arena, new_addr, alloc_size, 0, false,
|
||||||
false);
|
false);
|
||||||
node = extent_tree_ad_search(chunks_ad, &key);
|
node = extent_tree_ad_search(chunks_ad, &key);
|
||||||
} else {
|
} else {
|
||||||
node = chunk_first_best_fit(arena, chunks_szad, chunks_ad,
|
node = chunk_first_best_fit(arena, chunks_szsnad, alloc_size);
|
||||||
alloc_size);
|
|
||||||
}
|
}
|
||||||
if (node == NULL || (new_addr != NULL && extent_node_size_get(node) <
|
if (node == NULL || (new_addr != NULL && extent_node_size_get(node) <
|
||||||
size)) {
|
size)) {
|
||||||
@@ -243,6 +244,7 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
assert(extent_node_size_get(node) >= leadsize + size);
|
assert(extent_node_size_get(node) >= leadsize + size);
|
||||||
trailsize = extent_node_size_get(node) - leadsize - size;
|
trailsize = extent_node_size_get(node) - leadsize - size;
|
||||||
ret = (void *)((uintptr_t)extent_node_addr_get(node) + leadsize);
|
ret = (void *)((uintptr_t)extent_node_addr_get(node) + leadsize);
|
||||||
|
*sn = extent_node_sn_get(node);
|
||||||
zeroed = extent_node_zeroed_get(node);
|
zeroed = extent_node_zeroed_get(node);
|
||||||
if (zeroed)
|
if (zeroed)
|
||||||
*zero = true;
|
*zero = true;
|
||||||
@@ -257,13 +259,13 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
/* Remove node from the tree. */
|
/* Remove node from the tree. */
|
||||||
extent_tree_szad_remove(chunks_szad, node);
|
extent_tree_szsnad_remove(chunks_szsnad, node);
|
||||||
extent_tree_ad_remove(chunks_ad, node);
|
extent_tree_ad_remove(chunks_ad, node);
|
||||||
arena_chunk_cache_maybe_remove(arena, node, cache);
|
arena_chunk_cache_maybe_remove(arena, node, cache);
|
||||||
if (leadsize != 0) {
|
if (leadsize != 0) {
|
||||||
/* Insert the leading space as a smaller chunk. */
|
/* Insert the leading space as a smaller chunk. */
|
||||||
extent_node_size_set(node, leadsize);
|
extent_node_size_set(node, leadsize);
|
||||||
extent_tree_szad_insert(chunks_szad, node);
|
extent_tree_szsnad_insert(chunks_szsnad, node);
|
||||||
extent_tree_ad_insert(chunks_ad, node);
|
extent_tree_ad_insert(chunks_ad, node);
|
||||||
arena_chunk_cache_maybe_insert(arena, node, cache);
|
arena_chunk_cache_maybe_insert(arena, node, cache);
|
||||||
node = NULL;
|
node = NULL;
|
||||||
@@ -275,9 +277,9 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
if (dalloc_node && node != NULL)
|
if (dalloc_node && node != NULL)
|
||||||
arena_node_dalloc(tsdn, arena, node);
|
arena_node_dalloc(tsdn, arena, node);
|
||||||
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
|
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
|
||||||
chunk_record(tsdn, arena, chunk_hooks, chunks_szad,
|
chunk_record(tsdn, arena, chunk_hooks, chunks_szsnad,
|
||||||
chunks_ad, cache, ret, size + trailsize, zeroed,
|
chunks_ad, cache, ret, size + trailsize, *sn,
|
||||||
committed);
|
zeroed, committed);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
/* Insert the trailing space as a smaller chunk. */
|
/* Insert the trailing space as a smaller chunk. */
|
||||||
@@ -286,22 +288,22 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
|
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
|
||||||
chunk_record(tsdn, arena, chunk_hooks,
|
chunk_record(tsdn, arena, chunk_hooks,
|
||||||
chunks_szad, chunks_ad, cache, ret, size +
|
chunks_szsnad, chunks_ad, cache, ret, size
|
||||||
trailsize, zeroed, committed);
|
+ trailsize, *sn, zeroed, committed);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extent_node_init(node, arena, (void *)((uintptr_t)(ret) + size),
|
extent_node_init(node, arena, (void *)((uintptr_t)(ret) + size),
|
||||||
trailsize, zeroed, committed);
|
trailsize, *sn, zeroed, committed);
|
||||||
extent_tree_szad_insert(chunks_szad, node);
|
extent_tree_szsnad_insert(chunks_szsnad, node);
|
||||||
extent_tree_ad_insert(chunks_ad, node);
|
extent_tree_ad_insert(chunks_ad, node);
|
||||||
arena_chunk_cache_maybe_insert(arena, node, cache);
|
arena_chunk_cache_maybe_insert(arena, node, cache);
|
||||||
node = NULL;
|
node = NULL;
|
||||||
}
|
}
|
||||||
if (!committed && chunk_hooks->commit(ret, size, 0, size, arena->ind)) {
|
if (!committed && chunk_hooks->commit(ret, size, 0, size, arena->ind)) {
|
||||||
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
|
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
|
||||||
chunk_record(tsdn, arena, chunk_hooks, chunks_szad, chunks_ad,
|
chunk_record(tsdn, arena, chunk_hooks, chunks_szsnad, chunks_ad,
|
||||||
cache, ret, size, zeroed, committed);
|
cache, ret, size, *sn, zeroed, committed);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
|
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
|
||||||
@@ -316,10 +318,11 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
size_t i;
|
size_t i;
|
||||||
size_t *p = (size_t *)(uintptr_t)ret;
|
size_t *p = (size_t *)(uintptr_t)ret;
|
||||||
|
|
||||||
JEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ret, size);
|
|
||||||
for (i = 0; i < size / sizeof(size_t); i++)
|
for (i = 0; i < size / sizeof(size_t); i++)
|
||||||
assert(p[i] == 0);
|
assert(p[i] == 0);
|
||||||
}
|
}
|
||||||
|
if (config_valgrind)
|
||||||
|
JEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ret, size);
|
||||||
}
|
}
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
@@ -384,23 +387,21 @@ chunk_alloc_base(size_t size)
|
|||||||
|
|
||||||
void *
|
void *
|
||||||
chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
||||||
void *new_addr, size_t size, size_t alignment, bool *zero, bool dalloc_node)
|
void *new_addr, size_t size, size_t alignment, size_t *sn, bool *zero,
|
||||||
|
bool *commit, bool dalloc_node)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
bool commit;
|
|
||||||
|
|
||||||
assert(size != 0);
|
assert(size != 0);
|
||||||
assert((size & chunksize_mask) == 0);
|
assert((size & chunksize_mask) == 0);
|
||||||
assert(alignment != 0);
|
assert(alignment != 0);
|
||||||
assert((alignment & chunksize_mask) == 0);
|
assert((alignment & chunksize_mask) == 0);
|
||||||
|
|
||||||
commit = true;
|
|
||||||
ret = chunk_recycle(tsdn, arena, chunk_hooks,
|
ret = chunk_recycle(tsdn, arena, chunk_hooks,
|
||||||
&arena->chunks_szad_cached, &arena->chunks_ad_cached, true,
|
&arena->chunks_szsnad_cached, &arena->chunks_ad_cached, true,
|
||||||
new_addr, size, alignment, zero, &commit, dalloc_node);
|
new_addr, size, alignment, sn, zero, commit, dalloc_node);
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
assert(commit);
|
|
||||||
if (config_valgrind)
|
if (config_valgrind)
|
||||||
JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
|
JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -421,15 +422,11 @@ chunk_arena_get(tsdn_t *tsdn, unsigned arena_ind)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
chunk_alloc_default(void *new_addr, size_t size, size_t alignment, bool *zero,
|
chunk_alloc_default_impl(tsdn_t *tsdn, arena_t *arena, void *new_addr,
|
||||||
bool *commit, unsigned arena_ind)
|
size_t size, size_t alignment, bool *zero, bool *commit)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
tsdn_t *tsdn;
|
|
||||||
arena_t *arena;
|
|
||||||
|
|
||||||
tsdn = tsdn_fetch();
|
|
||||||
arena = chunk_arena_get(tsdn, arena_ind);
|
|
||||||
ret = chunk_alloc_core(tsdn, arena, new_addr, size, alignment, zero,
|
ret = chunk_alloc_core(tsdn, arena, new_addr, size, alignment, zero,
|
||||||
commit, arena->dss_prec);
|
commit, arena->dss_prec);
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
@@ -440,9 +437,24 @@ chunk_alloc_default(void *new_addr, size_t size, size_t alignment, bool *zero,
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
chunk_alloc_default(void *new_addr, size_t size, size_t alignment, bool *zero,
|
||||||
|
bool *commit, unsigned arena_ind)
|
||||||
|
{
|
||||||
|
tsdn_t *tsdn;
|
||||||
|
arena_t *arena;
|
||||||
|
|
||||||
|
tsdn = tsdn_fetch();
|
||||||
|
arena = chunk_arena_get(tsdn, arena_ind);
|
||||||
|
|
||||||
|
return (chunk_alloc_default_impl(tsdn, arena, new_addr, size, alignment,
|
||||||
|
zero, commit));
|
||||||
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
chunk_alloc_retained(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
chunk_alloc_retained(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
||||||
void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit)
|
void *new_addr, size_t size, size_t alignment, size_t *sn, bool *zero,
|
||||||
|
bool *commit)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
@@ -452,8 +464,8 @@ chunk_alloc_retained(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
assert((alignment & chunksize_mask) == 0);
|
assert((alignment & chunksize_mask) == 0);
|
||||||
|
|
||||||
ret = chunk_recycle(tsdn, arena, chunk_hooks,
|
ret = chunk_recycle(tsdn, arena, chunk_hooks,
|
||||||
&arena->chunks_szad_retained, &arena->chunks_ad_retained, false,
|
&arena->chunks_szsnad_retained, &arena->chunks_ad_retained, false,
|
||||||
new_addr, size, alignment, zero, commit, true);
|
new_addr, size, alignment, sn, zero, commit, true);
|
||||||
|
|
||||||
if (config_stats && ret != NULL)
|
if (config_stats && ret != NULL)
|
||||||
arena->stats.retained -= size;
|
arena->stats.retained -= size;
|
||||||
@@ -463,30 +475,42 @@ chunk_alloc_retained(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
|
|
||||||
void *
|
void *
|
||||||
chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
||||||
void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit)
|
void *new_addr, size_t size, size_t alignment, size_t *sn, bool *zero,
|
||||||
|
bool *commit)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
chunk_hooks_assure_initialized(tsdn, arena, chunk_hooks);
|
chunk_hooks_assure_initialized(tsdn, arena, chunk_hooks);
|
||||||
|
|
||||||
ret = chunk_alloc_retained(tsdn, arena, chunk_hooks, new_addr, size,
|
ret = chunk_alloc_retained(tsdn, arena, chunk_hooks, new_addr, size,
|
||||||
alignment, zero, commit);
|
alignment, sn, zero, commit);
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
ret = chunk_hooks->alloc(new_addr, size, alignment, zero,
|
if (chunk_hooks->alloc == chunk_alloc_default) {
|
||||||
commit, arena->ind);
|
/* Call directly to propagate tsdn. */
|
||||||
|
ret = chunk_alloc_default_impl(tsdn, arena, new_addr,
|
||||||
|
size, alignment, zero, commit);
|
||||||
|
} else {
|
||||||
|
ret = chunk_hooks->alloc(new_addr, size, alignment,
|
||||||
|
zero, commit, arena->ind);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
|
*sn = arena_extent_sn_next(arena);
|
||||||
|
|
||||||
|
if (config_valgrind && chunk_hooks->alloc !=
|
||||||
|
chunk_alloc_default)
|
||||||
|
JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, chunksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config_valgrind && chunk_hooks->alloc != chunk_alloc_default)
|
|
||||||
JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, chunksize);
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
||||||
extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, bool cache,
|
extent_tree_t *chunks_szsnad, extent_tree_t *chunks_ad, bool cache,
|
||||||
void *chunk, size_t size, bool zeroed, bool committed)
|
void *chunk, size_t size, size_t sn, bool zeroed, bool committed)
|
||||||
{
|
{
|
||||||
bool unzeroed;
|
bool unzeroed;
|
||||||
extent_node_t *node, *prev;
|
extent_node_t *node, *prev;
|
||||||
@@ -498,7 +522,7 @@ chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
|
|
||||||
malloc_mutex_lock(tsdn, &arena->chunks_mtx);
|
malloc_mutex_lock(tsdn, &arena->chunks_mtx);
|
||||||
chunk_hooks_assure_initialized_locked(tsdn, arena, chunk_hooks);
|
chunk_hooks_assure_initialized_locked(tsdn, arena, chunk_hooks);
|
||||||
extent_node_init(&key, arena, (void *)((uintptr_t)chunk + size), 0,
|
extent_node_init(&key, arena, (void *)((uintptr_t)chunk + size), 0, 0,
|
||||||
false, false);
|
false, false);
|
||||||
node = extent_tree_ad_nsearch(chunks_ad, &key);
|
node = extent_tree_ad_nsearch(chunks_ad, &key);
|
||||||
/* Try to coalesce forward. */
|
/* Try to coalesce forward. */
|
||||||
@@ -510,15 +534,17 @@ chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
/*
|
/*
|
||||||
* Coalesce chunk with the following address range. This does
|
* Coalesce chunk with the following address range. This does
|
||||||
* not change the position within chunks_ad, so only
|
* not change the position within chunks_ad, so only
|
||||||
* remove/insert from/into chunks_szad.
|
* remove/insert from/into chunks_szsnad.
|
||||||
*/
|
*/
|
||||||
extent_tree_szad_remove(chunks_szad, node);
|
extent_tree_szsnad_remove(chunks_szsnad, node);
|
||||||
arena_chunk_cache_maybe_remove(arena, node, cache);
|
arena_chunk_cache_maybe_remove(arena, node, cache);
|
||||||
extent_node_addr_set(node, chunk);
|
extent_node_addr_set(node, chunk);
|
||||||
extent_node_size_set(node, size + extent_node_size_get(node));
|
extent_node_size_set(node, size + extent_node_size_get(node));
|
||||||
|
if (sn < extent_node_sn_get(node))
|
||||||
|
extent_node_sn_set(node, sn);
|
||||||
extent_node_zeroed_set(node, extent_node_zeroed_get(node) &&
|
extent_node_zeroed_set(node, extent_node_zeroed_get(node) &&
|
||||||
!unzeroed);
|
!unzeroed);
|
||||||
extent_tree_szad_insert(chunks_szad, node);
|
extent_tree_szsnad_insert(chunks_szsnad, node);
|
||||||
arena_chunk_cache_maybe_insert(arena, node, cache);
|
arena_chunk_cache_maybe_insert(arena, node, cache);
|
||||||
} else {
|
} else {
|
||||||
/* Coalescing forward failed, so insert a new node. */
|
/* Coalescing forward failed, so insert a new node. */
|
||||||
@@ -536,10 +562,10 @@ chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
}
|
}
|
||||||
goto label_return;
|
goto label_return;
|
||||||
}
|
}
|
||||||
extent_node_init(node, arena, chunk, size, !unzeroed,
|
extent_node_init(node, arena, chunk, size, sn, !unzeroed,
|
||||||
committed);
|
committed);
|
||||||
extent_tree_ad_insert(chunks_ad, node);
|
extent_tree_ad_insert(chunks_ad, node);
|
||||||
extent_tree_szad_insert(chunks_szad, node);
|
extent_tree_szsnad_insert(chunks_szsnad, node);
|
||||||
arena_chunk_cache_maybe_insert(arena, node, cache);
|
arena_chunk_cache_maybe_insert(arena, node, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,19 +579,21 @@ chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
/*
|
/*
|
||||||
* Coalesce chunk with the previous address range. This does
|
* Coalesce chunk with the previous address range. This does
|
||||||
* not change the position within chunks_ad, so only
|
* not change the position within chunks_ad, so only
|
||||||
* remove/insert node from/into chunks_szad.
|
* remove/insert node from/into chunks_szsnad.
|
||||||
*/
|
*/
|
||||||
extent_tree_szad_remove(chunks_szad, prev);
|
extent_tree_szsnad_remove(chunks_szsnad, prev);
|
||||||
extent_tree_ad_remove(chunks_ad, prev);
|
extent_tree_ad_remove(chunks_ad, prev);
|
||||||
arena_chunk_cache_maybe_remove(arena, prev, cache);
|
arena_chunk_cache_maybe_remove(arena, prev, cache);
|
||||||
extent_tree_szad_remove(chunks_szad, node);
|
extent_tree_szsnad_remove(chunks_szsnad, node);
|
||||||
arena_chunk_cache_maybe_remove(arena, node, cache);
|
arena_chunk_cache_maybe_remove(arena, node, cache);
|
||||||
extent_node_addr_set(node, extent_node_addr_get(prev));
|
extent_node_addr_set(node, extent_node_addr_get(prev));
|
||||||
extent_node_size_set(node, extent_node_size_get(prev) +
|
extent_node_size_set(node, extent_node_size_get(prev) +
|
||||||
extent_node_size_get(node));
|
extent_node_size_get(node));
|
||||||
|
if (extent_node_sn_get(prev) < extent_node_sn_get(node))
|
||||||
|
extent_node_sn_set(node, extent_node_sn_get(prev));
|
||||||
extent_node_zeroed_set(node, extent_node_zeroed_get(prev) &&
|
extent_node_zeroed_set(node, extent_node_zeroed_get(prev) &&
|
||||||
extent_node_zeroed_get(node));
|
extent_node_zeroed_get(node));
|
||||||
extent_tree_szad_insert(chunks_szad, node);
|
extent_tree_szsnad_insert(chunks_szsnad, node);
|
||||||
arena_chunk_cache_maybe_insert(arena, node, cache);
|
arena_chunk_cache_maybe_insert(arena, node, cache);
|
||||||
|
|
||||||
arena_node_dalloc(tsdn, arena, prev);
|
arena_node_dalloc(tsdn, arena, prev);
|
||||||
@@ -577,7 +605,7 @@ label_return:
|
|||||||
|
|
||||||
void
|
void
|
||||||
chunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
chunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
||||||
void *chunk, size_t size, bool committed)
|
void *chunk, size_t size, size_t sn, bool committed)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert(chunk != NULL);
|
assert(chunk != NULL);
|
||||||
@@ -585,25 +613,34 @@ chunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
assert(size != 0);
|
assert(size != 0);
|
||||||
assert((size & chunksize_mask) == 0);
|
assert((size & chunksize_mask) == 0);
|
||||||
|
|
||||||
chunk_record(tsdn, arena, chunk_hooks, &arena->chunks_szad_cached,
|
chunk_record(tsdn, arena, chunk_hooks, &arena->chunks_szsnad_cached,
|
||||||
&arena->chunks_ad_cached, true, chunk, size, false, committed);
|
&arena->chunks_ad_cached, true, chunk, size, sn, false,
|
||||||
|
committed);
|
||||||
arena_maybe_purge(tsdn, arena);
|
arena_maybe_purge(tsdn, arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
chunk_dalloc_default_impl(void *chunk, size_t size)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!have_dss || !chunk_in_dss(chunk))
|
||||||
|
return (chunk_dalloc_mmap(chunk, size));
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
chunk_dalloc_default(void *chunk, size_t size, bool committed,
|
chunk_dalloc_default(void *chunk, size_t size, bool committed,
|
||||||
unsigned arena_ind)
|
unsigned arena_ind)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!have_dss || !chunk_in_dss(tsdn_fetch(), chunk))
|
return (chunk_dalloc_default_impl(chunk, size));
|
||||||
return (chunk_dalloc_mmap(chunk, size));
|
|
||||||
return (true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
||||||
void *chunk, size_t size, bool zeroed, bool committed)
|
void *chunk, size_t size, size_t sn, bool zeroed, bool committed)
|
||||||
{
|
{
|
||||||
|
bool err;
|
||||||
|
|
||||||
assert(chunk != NULL);
|
assert(chunk != NULL);
|
||||||
assert(CHUNK_ADDR2BASE(chunk) == chunk);
|
assert(CHUNK_ADDR2BASE(chunk) == chunk);
|
||||||
@@ -612,7 +649,13 @@ chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
|
|
||||||
chunk_hooks_assure_initialized(tsdn, arena, chunk_hooks);
|
chunk_hooks_assure_initialized(tsdn, arena, chunk_hooks);
|
||||||
/* Try to deallocate. */
|
/* Try to deallocate. */
|
||||||
if (!chunk_hooks->dalloc(chunk, size, committed, arena->ind))
|
if (chunk_hooks->dalloc == chunk_dalloc_default) {
|
||||||
|
/* Call directly to propagate tsdn. */
|
||||||
|
err = chunk_dalloc_default_impl(chunk, size);
|
||||||
|
} else
|
||||||
|
err = chunk_hooks->dalloc(chunk, size, committed, arena->ind);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
return;
|
return;
|
||||||
/* Try to decommit; purge if that fails. */
|
/* Try to decommit; purge if that fails. */
|
||||||
if (committed) {
|
if (committed) {
|
||||||
@@ -621,8 +664,9 @@ chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
}
|
}
|
||||||
zeroed = !committed || !chunk_hooks->purge(chunk, size, 0, size,
|
zeroed = !committed || !chunk_hooks->purge(chunk, size, 0, size,
|
||||||
arena->ind);
|
arena->ind);
|
||||||
chunk_record(tsdn, arena, chunk_hooks, &arena->chunks_szad_retained,
|
chunk_record(tsdn, arena, chunk_hooks, &arena->chunks_szsnad_retained,
|
||||||
&arena->chunks_ad_retained, false, chunk, size, zeroed, committed);
|
&arena->chunks_ad_retained, false, chunk, size, sn, zeroed,
|
||||||
|
committed);
|
||||||
|
|
||||||
if (config_stats)
|
if (config_stats)
|
||||||
arena->stats.retained += size;
|
arena->stats.retained += size;
|
||||||
@@ -681,26 +725,30 @@ chunk_split_default(void *chunk, size_t size, size_t size_a, size_t size_b,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
chunk_merge_default(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,
|
chunk_merge_default_impl(void *chunk_a, void *chunk_b)
|
||||||
bool committed, unsigned arena_ind)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!maps_coalesce)
|
if (!maps_coalesce)
|
||||||
return (true);
|
return (true);
|
||||||
if (have_dss) {
|
if (have_dss && !chunk_dss_mergeable(chunk_a, chunk_b))
|
||||||
tsdn_t *tsdn = tsdn_fetch();
|
return (true);
|
||||||
if (chunk_in_dss(tsdn, chunk_a) != chunk_in_dss(tsdn, chunk_b))
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
chunk_merge_default(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,
|
||||||
|
bool committed, unsigned arena_ind)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (chunk_merge_default_impl(chunk_a, chunk_b));
|
||||||
|
}
|
||||||
|
|
||||||
static rtree_node_elm_t *
|
static rtree_node_elm_t *
|
||||||
chunks_rtree_node_alloc(size_t nelms)
|
chunks_rtree_node_alloc(size_t nelms)
|
||||||
{
|
{
|
||||||
|
|
||||||
return ((rtree_node_elm_t *)base_alloc(tsdn_fetch(), nelms *
|
return ((rtree_node_elm_t *)base_alloc(TSDN_NULL, nelms *
|
||||||
sizeof(rtree_node_elm_t)));
|
sizeof(rtree_node_elm_t)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -737,32 +785,11 @@ chunk_boot(void)
|
|||||||
chunksize_mask = chunksize - 1;
|
chunksize_mask = chunksize - 1;
|
||||||
chunk_npages = (chunksize >> LG_PAGE);
|
chunk_npages = (chunksize >> LG_PAGE);
|
||||||
|
|
||||||
if (have_dss && chunk_dss_boot())
|
if (have_dss)
|
||||||
return (true);
|
chunk_dss_boot();
|
||||||
if (rtree_new(&chunks_rtree, (unsigned)((ZU(1) << (LG_SIZEOF_PTR+3)) -
|
if (rtree_new(&chunks_rtree, (unsigned)((ZU(1) << (LG_SIZEOF_PTR+3)) -
|
||||||
opt_lg_chunk), chunks_rtree_node_alloc, NULL))
|
opt_lg_chunk), chunks_rtree_node_alloc, NULL))
|
||||||
return (true);
|
return (true);
|
||||||
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
chunk_prefork(tsdn_t *tsdn)
|
|
||||||
{
|
|
||||||
|
|
||||||
chunk_dss_prefork(tsdn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
chunk_postfork_parent(tsdn_t *tsdn)
|
|
||||||
{
|
|
||||||
|
|
||||||
chunk_dss_postfork_parent(tsdn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
chunk_postfork_child(tsdn_t *tsdn)
|
|
||||||
{
|
|
||||||
|
|
||||||
chunk_dss_postfork_child(tsdn);
|
|
||||||
}
|
|
||||||
|
|||||||
196
src/chunk_dss.c
196
src/chunk_dss.c
@@ -10,20 +10,19 @@ const char *dss_prec_names[] = {
|
|||||||
"N/A"
|
"N/A"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Current dss precedence default, used when creating new arenas. */
|
|
||||||
static dss_prec_t dss_prec_default = DSS_PREC_DEFAULT;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Protects sbrk() calls. This avoids malloc races among threads, though it
|
* Current dss precedence default, used when creating new arenas. NB: This is
|
||||||
* does not protect against races with threads that call sbrk() directly.
|
* stored as unsigned rather than dss_prec_t because in principle there's no
|
||||||
|
* guarantee that sizeof(dss_prec_t) is the same as sizeof(unsigned), and we use
|
||||||
|
* atomic operations to synchronize the setting.
|
||||||
*/
|
*/
|
||||||
static malloc_mutex_t dss_mtx;
|
static unsigned dss_prec_default = (unsigned)DSS_PREC_DEFAULT;
|
||||||
|
|
||||||
/* Base address of the DSS. */
|
/* Base address of the DSS. */
|
||||||
static void *dss_base;
|
static void *dss_base;
|
||||||
/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */
|
/* Atomic boolean indicating whether the DSS is exhausted. */
|
||||||
static void *dss_prev;
|
static unsigned dss_exhausted;
|
||||||
/* Current upper limit on DSS addresses. */
|
/* Atomic current upper limit on DSS addresses. */
|
||||||
static void *dss_max;
|
static void *dss_max;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@@ -41,30 +40,59 @@ chunk_dss_sbrk(intptr_t increment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dss_prec_t
|
dss_prec_t
|
||||||
chunk_dss_prec_get(tsdn_t *tsdn)
|
chunk_dss_prec_get(void)
|
||||||
{
|
{
|
||||||
dss_prec_t ret;
|
dss_prec_t ret;
|
||||||
|
|
||||||
if (!have_dss)
|
if (!have_dss)
|
||||||
return (dss_prec_disabled);
|
return (dss_prec_disabled);
|
||||||
malloc_mutex_lock(tsdn, &dss_mtx);
|
ret = (dss_prec_t)atomic_read_u(&dss_prec_default);
|
||||||
ret = dss_prec_default;
|
|
||||||
malloc_mutex_unlock(tsdn, &dss_mtx);
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
chunk_dss_prec_set(tsdn_t *tsdn, dss_prec_t dss_prec)
|
chunk_dss_prec_set(dss_prec_t dss_prec)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!have_dss)
|
if (!have_dss)
|
||||||
return (dss_prec != dss_prec_disabled);
|
return (dss_prec != dss_prec_disabled);
|
||||||
malloc_mutex_lock(tsdn, &dss_mtx);
|
atomic_write_u(&dss_prec_default, (unsigned)dss_prec);
|
||||||
dss_prec_default = dss_prec;
|
|
||||||
malloc_mutex_unlock(tsdn, &dss_mtx);
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
chunk_dss_max_update(void *new_addr)
|
||||||
|
{
|
||||||
|
void *max_cur;
|
||||||
|
spin_t spinner;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the current end of the DSS as max_cur and assure that dss_max is
|
||||||
|
* up to date.
|
||||||
|
*/
|
||||||
|
spin_init(&spinner);
|
||||||
|
while (true) {
|
||||||
|
void *max_prev = atomic_read_p(&dss_max);
|
||||||
|
|
||||||
|
max_cur = chunk_dss_sbrk(0);
|
||||||
|
if ((uintptr_t)max_prev > (uintptr_t)max_cur) {
|
||||||
|
/*
|
||||||
|
* Another thread optimistically updated dss_max. Wait
|
||||||
|
* for it to finish.
|
||||||
|
*/
|
||||||
|
spin_adaptive(&spinner);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!atomic_cas_p(&dss_max, max_prev, max_cur))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Fixed new_addr can only be supported if it is at the edge of DSS. */
|
||||||
|
if (new_addr != NULL && max_cur != new_addr)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
return (max_cur);
|
||||||
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
|
chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
|
||||||
size_t alignment, bool *zero, bool *commit)
|
size_t alignment, bool *zero, bool *commit)
|
||||||
@@ -80,28 +108,20 @@ chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
|
|||||||
if ((intptr_t)size < 0)
|
if ((intptr_t)size < 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
malloc_mutex_lock(tsdn, &dss_mtx);
|
if (!atomic_read_u(&dss_exhausted)) {
|
||||||
if (dss_prev != (void *)-1) {
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The loop is necessary to recover from races with other
|
* The loop is necessary to recover from races with other
|
||||||
* threads that are using the DSS for something other than
|
* threads that are using the DSS for something other than
|
||||||
* malloc.
|
* malloc.
|
||||||
*/
|
*/
|
||||||
do {
|
while (true) {
|
||||||
void *ret, *cpad, *dss_next;
|
void *ret, *cpad, *max_cur, *dss_next, *dss_prev;
|
||||||
size_t gap_size, cpad_size;
|
size_t gap_size, cpad_size;
|
||||||
intptr_t incr;
|
intptr_t incr;
|
||||||
/* Avoid an unnecessary system call. */
|
|
||||||
if (new_addr != NULL && dss_max != new_addr)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Get the current end of the DSS. */
|
max_cur = chunk_dss_max_update(new_addr);
|
||||||
dss_max = chunk_dss_sbrk(0);
|
if (max_cur == NULL)
|
||||||
|
goto label_oom;
|
||||||
/* Make sure the earlier condition still holds. */
|
|
||||||
if (new_addr != NULL && dss_max != new_addr)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate how much padding is necessary to
|
* Calculate how much padding is necessary to
|
||||||
@@ -120,23 +140,30 @@ chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
|
|||||||
cpad_size = (uintptr_t)ret - (uintptr_t)cpad;
|
cpad_size = (uintptr_t)ret - (uintptr_t)cpad;
|
||||||
dss_next = (void *)((uintptr_t)ret + size);
|
dss_next = (void *)((uintptr_t)ret + size);
|
||||||
if ((uintptr_t)ret < (uintptr_t)dss_max ||
|
if ((uintptr_t)ret < (uintptr_t)dss_max ||
|
||||||
(uintptr_t)dss_next < (uintptr_t)dss_max) {
|
(uintptr_t)dss_next < (uintptr_t)dss_max)
|
||||||
/* Wrap-around. */
|
goto label_oom; /* Wrap-around. */
|
||||||
malloc_mutex_unlock(tsdn, &dss_mtx);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
incr = gap_size + cpad_size + size;
|
incr = gap_size + cpad_size + size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optimistically update dss_max, and roll back below if
|
||||||
|
* sbrk() fails. No other thread will try to extend the
|
||||||
|
* DSS while dss_max is greater than the current DSS
|
||||||
|
* max reported by sbrk(0).
|
||||||
|
*/
|
||||||
|
if (atomic_cas_p(&dss_max, max_cur, dss_next))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Try to allocate. */
|
||||||
dss_prev = chunk_dss_sbrk(incr);
|
dss_prev = chunk_dss_sbrk(incr);
|
||||||
if (dss_prev == dss_max) {
|
if (dss_prev == max_cur) {
|
||||||
/* Success. */
|
/* Success. */
|
||||||
dss_max = dss_next;
|
|
||||||
malloc_mutex_unlock(tsdn, &dss_mtx);
|
|
||||||
if (cpad_size != 0) {
|
if (cpad_size != 0) {
|
||||||
chunk_hooks_t chunk_hooks =
|
chunk_hooks_t chunk_hooks =
|
||||||
CHUNK_HOOKS_INITIALIZER;
|
CHUNK_HOOKS_INITIALIZER;
|
||||||
chunk_dalloc_wrapper(tsdn, arena,
|
chunk_dalloc_wrapper(tsdn, arena,
|
||||||
&chunk_hooks, cpad, cpad_size,
|
&chunk_hooks, cpad, cpad_size,
|
||||||
false, true);
|
arena_extent_sn_next(arena), false,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
if (*zero) {
|
if (*zero) {
|
||||||
JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(
|
JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(
|
||||||
@@ -147,68 +174,65 @@ chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
|
|||||||
*commit = pages_decommit(ret, size);
|
*commit = pages_decommit(ret, size);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
} while (dss_prev != (void *)-1);
|
|
||||||
}
|
|
||||||
malloc_mutex_unlock(tsdn, &dss_mtx);
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Failure, whether due to OOM or a race with a raw
|
||||||
|
* sbrk() call from outside the allocator. Try to roll
|
||||||
|
* back optimistic dss_max update; if rollback fails,
|
||||||
|
* it's due to another caller of this function having
|
||||||
|
* succeeded since this invocation started, in which
|
||||||
|
* case rollback is not necessary.
|
||||||
|
*/
|
||||||
|
atomic_cas_p(&dss_max, dss_next, max_cur);
|
||||||
|
if (dss_prev == (void *)-1) {
|
||||||
|
/* OOM. */
|
||||||
|
atomic_write_u(&dss_exhausted, (unsigned)true);
|
||||||
|
goto label_oom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
label_oom:
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
chunk_in_dss(tsdn_t *tsdn, void *chunk)
|
chunk_in_dss_helper(void *chunk, void *max)
|
||||||
{
|
{
|
||||||
bool ret;
|
|
||||||
|
|
||||||
cassert(have_dss);
|
return ((uintptr_t)chunk >= (uintptr_t)dss_base && (uintptr_t)chunk <
|
||||||
|
(uintptr_t)max);
|
||||||
malloc_mutex_lock(tsdn, &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(tsdn, &dss_mtx);
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
chunk_in_dss(void *chunk)
|
||||||
|
{
|
||||||
|
|
||||||
|
cassert(have_dss);
|
||||||
|
|
||||||
|
return (chunk_in_dss_helper(chunk, atomic_read_p(&dss_max)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
chunk_dss_mergeable(void *chunk_a, void *chunk_b)
|
||||||
|
{
|
||||||
|
void *max;
|
||||||
|
|
||||||
|
cassert(have_dss);
|
||||||
|
|
||||||
|
max = atomic_read_p(&dss_max);
|
||||||
|
return (chunk_in_dss_helper(chunk_a, max) ==
|
||||||
|
chunk_in_dss_helper(chunk_b, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
chunk_dss_boot(void)
|
chunk_dss_boot(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
cassert(have_dss);
|
cassert(have_dss);
|
||||||
|
|
||||||
if (malloc_mutex_init(&dss_mtx, "dss", WITNESS_RANK_DSS))
|
|
||||||
return (true);
|
|
||||||
dss_base = chunk_dss_sbrk(0);
|
dss_base = chunk_dss_sbrk(0);
|
||||||
dss_prev = dss_base;
|
dss_exhausted = (unsigned)(dss_base == (void *)-1);
|
||||||
dss_max = dss_base;
|
dss_max = dss_base;
|
||||||
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
chunk_dss_prefork(tsdn_t *tsdn)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (have_dss)
|
|
||||||
malloc_mutex_prefork(tsdn, &dss_mtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
chunk_dss_postfork_parent(tsdn_t *tsdn)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (have_dss)
|
|
||||||
malloc_mutex_postfork_parent(tsdn, &dss_mtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
chunk_dss_postfork_child(tsdn_t *tsdn)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (have_dss)
|
|
||||||
malloc_mutex_postfork_child(tsdn, &dss_mtx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ chunk_alloc_mmap_slow(size_t size, size_t alignment, bool *zero, bool *commit)
|
|||||||
void *ret;
|
void *ret;
|
||||||
size_t alloc_size;
|
size_t alloc_size;
|
||||||
|
|
||||||
alloc_size = size + alignment;
|
alloc_size = size + alignment - PAGE;
|
||||||
/* Beware size_t wrap-around. */
|
/* Beware size_t wrap-around. */
|
||||||
if (alloc_size < size)
|
if (alloc_size < size)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|||||||
47
src/ckh.c
47
src/ckh.c
@@ -40,8 +40,8 @@
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Function prototypes for non-inline static functions. */
|
/* Function prototypes for non-inline static functions. */
|
||||||
|
|
||||||
static bool ckh_grow(tsdn_t *tsdn, ckh_t *ckh);
|
static bool ckh_grow(tsd_t *tsd, ckh_t *ckh);
|
||||||
static void ckh_shrink(tsdn_t *tsdn, ckh_t *ckh);
|
static void ckh_shrink(tsd_t *tsd, ckh_t *ckh);
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@@ -99,7 +99,8 @@ ckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key,
|
|||||||
* Cycle through the cells in the bucket, starting at a random position.
|
* Cycle through the cells in the bucket, starting at a random position.
|
||||||
* The randomness avoids worst-case search overhead as buckets fill up.
|
* The randomness avoids worst-case search overhead as buckets fill up.
|
||||||
*/
|
*/
|
||||||
offset = (unsigned)prng_lg_range(&ckh->prng_state, LG_CKH_BUCKET_CELLS);
|
offset = (unsigned)prng_lg_range_u64(&ckh->prng_state,
|
||||||
|
LG_CKH_BUCKET_CELLS);
|
||||||
for (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {
|
for (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {
|
||||||
cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) +
|
cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) +
|
||||||
((i + offset) & ((ZU(1) << LG_CKH_BUCKET_CELLS) - 1))];
|
((i + offset) & ((ZU(1) << LG_CKH_BUCKET_CELLS) - 1))];
|
||||||
@@ -141,7 +142,7 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey,
|
|||||||
* were an item for which both hashes indicated the same
|
* were an item for which both hashes indicated the same
|
||||||
* bucket.
|
* bucket.
|
||||||
*/
|
*/
|
||||||
i = (unsigned)prng_lg_range(&ckh->prng_state,
|
i = (unsigned)prng_lg_range_u64(&ckh->prng_state,
|
||||||
LG_CKH_BUCKET_CELLS);
|
LG_CKH_BUCKET_CELLS);
|
||||||
cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];
|
cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];
|
||||||
assert(cell->key != NULL);
|
assert(cell->key != NULL);
|
||||||
@@ -244,7 +245,7 @@ ckh_rebuild(ckh_t *ckh, ckhc_t *aTab)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ckh_grow(tsdn_t *tsdn, ckh_t *ckh)
|
ckh_grow(tsd_t *tsd, ckh_t *ckh)
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
ckhc_t *tab, *ttab;
|
ckhc_t *tab, *ttab;
|
||||||
@@ -270,8 +271,8 @@ ckh_grow(tsdn_t *tsdn, ckh_t *ckh)
|
|||||||
ret = true;
|
ret = true;
|
||||||
goto label_return;
|
goto label_return;
|
||||||
}
|
}
|
||||||
tab = (ckhc_t *)ipallocztm(tsdn, usize, CACHELINE, true, NULL,
|
tab = (ckhc_t *)ipallocztm(tsd_tsdn(tsd), usize, CACHELINE,
|
||||||
true, arena_ichoose(tsdn, NULL));
|
true, NULL, true, arena_ichoose(tsd, NULL));
|
||||||
if (tab == NULL) {
|
if (tab == NULL) {
|
||||||
ret = true;
|
ret = true;
|
||||||
goto label_return;
|
goto label_return;
|
||||||
@@ -283,12 +284,12 @@ ckh_grow(tsdn_t *tsdn, ckh_t *ckh)
|
|||||||
ckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;
|
ckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;
|
||||||
|
|
||||||
if (!ckh_rebuild(ckh, tab)) {
|
if (!ckh_rebuild(ckh, tab)) {
|
||||||
idalloctm(tsdn, tab, NULL, true, true);
|
idalloctm(tsd_tsdn(tsd), tab, NULL, true, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rebuilding failed, so back out partially rebuilt table. */
|
/* Rebuilding failed, so back out partially rebuilt table. */
|
||||||
idalloctm(tsdn, ckh->tab, NULL, true, true);
|
idalloctm(tsd_tsdn(tsd), ckh->tab, NULL, true, true);
|
||||||
ckh->tab = tab;
|
ckh->tab = tab;
|
||||||
ckh->lg_curbuckets = lg_prevbuckets;
|
ckh->lg_curbuckets = lg_prevbuckets;
|
||||||
}
|
}
|
||||||
@@ -299,7 +300,7 @@ label_return:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ckh_shrink(tsdn_t *tsdn, ckh_t *ckh)
|
ckh_shrink(tsd_t *tsd, ckh_t *ckh)
|
||||||
{
|
{
|
||||||
ckhc_t *tab, *ttab;
|
ckhc_t *tab, *ttab;
|
||||||
size_t usize;
|
size_t usize;
|
||||||
@@ -314,8 +315,8 @@ ckh_shrink(tsdn_t *tsdn, ckh_t *ckh)
|
|||||||
usize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);
|
usize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);
|
||||||
if (unlikely(usize == 0 || usize > HUGE_MAXCLASS))
|
if (unlikely(usize == 0 || usize > HUGE_MAXCLASS))
|
||||||
return;
|
return;
|
||||||
tab = (ckhc_t *)ipallocztm(tsdn, usize, CACHELINE, true, NULL, true,
|
tab = (ckhc_t *)ipallocztm(tsd_tsdn(tsd), usize, CACHELINE, true, NULL,
|
||||||
arena_ichoose(tsdn, NULL));
|
true, arena_ichoose(tsd, NULL));
|
||||||
if (tab == NULL) {
|
if (tab == NULL) {
|
||||||
/*
|
/*
|
||||||
* An OOM error isn't worth propagating, since it doesn't
|
* An OOM error isn't worth propagating, since it doesn't
|
||||||
@@ -330,7 +331,7 @@ ckh_shrink(tsdn_t *tsdn, ckh_t *ckh)
|
|||||||
ckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;
|
ckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;
|
||||||
|
|
||||||
if (!ckh_rebuild(ckh, tab)) {
|
if (!ckh_rebuild(ckh, tab)) {
|
||||||
idalloctm(tsdn, tab, NULL, true, true);
|
idalloctm(tsd_tsdn(tsd), tab, NULL, true, true);
|
||||||
#ifdef CKH_COUNT
|
#ifdef CKH_COUNT
|
||||||
ckh->nshrinks++;
|
ckh->nshrinks++;
|
||||||
#endif
|
#endif
|
||||||
@@ -338,7 +339,7 @@ ckh_shrink(tsdn_t *tsdn, ckh_t *ckh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rebuilding failed, so back out partially rebuilt table. */
|
/* Rebuilding failed, so back out partially rebuilt table. */
|
||||||
idalloctm(tsdn, ckh->tab, NULL, true, true);
|
idalloctm(tsd_tsdn(tsd), ckh->tab, NULL, true, true);
|
||||||
ckh->tab = tab;
|
ckh->tab = tab;
|
||||||
ckh->lg_curbuckets = lg_prevbuckets;
|
ckh->lg_curbuckets = lg_prevbuckets;
|
||||||
#ifdef CKH_COUNT
|
#ifdef CKH_COUNT
|
||||||
@@ -347,7 +348,7 @@ ckh_shrink(tsdn_t *tsdn, ckh_t *ckh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ckh_new(tsdn_t *tsdn, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
|
ckh_new(tsd_t *tsd, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
|
||||||
ckh_keycomp_t *keycomp)
|
ckh_keycomp_t *keycomp)
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
@@ -391,8 +392,8 @@ ckh_new(tsdn_t *tsdn, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
|
|||||||
ret = true;
|
ret = true;
|
||||||
goto label_return;
|
goto label_return;
|
||||||
}
|
}
|
||||||
ckh->tab = (ckhc_t *)ipallocztm(tsdn, usize, CACHELINE, true, NULL,
|
ckh->tab = (ckhc_t *)ipallocztm(tsd_tsdn(tsd), usize, CACHELINE, true,
|
||||||
true, arena_ichoose(tsdn, NULL));
|
NULL, true, arena_ichoose(tsd, NULL));
|
||||||
if (ckh->tab == NULL) {
|
if (ckh->tab == NULL) {
|
||||||
ret = true;
|
ret = true;
|
||||||
goto label_return;
|
goto label_return;
|
||||||
@@ -404,7 +405,7 @@ label_return:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ckh_delete(tsdn_t *tsdn, ckh_t *ckh)
|
ckh_delete(tsd_t *tsd, ckh_t *ckh)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert(ckh != NULL);
|
assert(ckh != NULL);
|
||||||
@@ -421,7 +422,7 @@ ckh_delete(tsdn_t *tsdn, ckh_t *ckh)
|
|||||||
(unsigned long long)ckh->nrelocs);
|
(unsigned long long)ckh->nrelocs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
idalloctm(tsdn, ckh->tab, NULL, true, true);
|
idalloctm(tsd_tsdn(tsd), ckh->tab, NULL, true, true);
|
||||||
if (config_debug)
|
if (config_debug)
|
||||||
memset(ckh, JEMALLOC_FREE_JUNK, sizeof(ckh_t));
|
memset(ckh, JEMALLOC_FREE_JUNK, sizeof(ckh_t));
|
||||||
}
|
}
|
||||||
@@ -456,7 +457,7 @@ ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ckh_insert(tsdn_t *tsdn, ckh_t *ckh, const void *key, const void *data)
|
ckh_insert(tsd_t *tsd, ckh_t *ckh, const void *key, const void *data)
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
@@ -468,7 +469,7 @@ ckh_insert(tsdn_t *tsdn, ckh_t *ckh, const void *key, const void *data)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (ckh_try_insert(ckh, &key, &data)) {
|
while (ckh_try_insert(ckh, &key, &data)) {
|
||||||
if (ckh_grow(tsdn, ckh)) {
|
if (ckh_grow(tsd, ckh)) {
|
||||||
ret = true;
|
ret = true;
|
||||||
goto label_return;
|
goto label_return;
|
||||||
}
|
}
|
||||||
@@ -480,7 +481,7 @@ label_return:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ckh_remove(tsdn_t *tsdn, ckh_t *ckh, const void *searchkey, void **key,
|
ckh_remove(tsd_t *tsd, ckh_t *ckh, const void *searchkey, void **key,
|
||||||
void **data)
|
void **data)
|
||||||
{
|
{
|
||||||
size_t cell;
|
size_t cell;
|
||||||
@@ -502,7 +503,7 @@ ckh_remove(tsdn_t *tsdn, ckh_t *ckh, const void *searchkey, void **key,
|
|||||||
+ LG_CKH_BUCKET_CELLS - 2)) && ckh->lg_curbuckets
|
+ LG_CKH_BUCKET_CELLS - 2)) && ckh->lg_curbuckets
|
||||||
> ckh->lg_minbuckets) {
|
> ckh->lg_minbuckets) {
|
||||||
/* Ignore error due to OOM. */
|
/* Ignore error due to OOM. */
|
||||||
ckh_shrink(tsdn, ckh);
|
ckh_shrink(tsd, ckh);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (false);
|
return (false);
|
||||||
|
|||||||
@@ -1478,7 +1478,7 @@ tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
|||||||
|
|
||||||
malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
|
malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
|
||||||
READONLY();
|
READONLY();
|
||||||
if (tcaches_create(tsd_tsdn(tsd), &tcache_ind)) {
|
if (tcaches_create(tsd, &tcache_ind)) {
|
||||||
ret = EFAULT;
|
ret = EFAULT;
|
||||||
goto label_return;
|
goto label_return;
|
||||||
}
|
}
|
||||||
@@ -1685,11 +1685,11 @@ arena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
|||||||
dss_prec_old = arena_dss_prec_get(tsd_tsdn(tsd), arena);
|
dss_prec_old = arena_dss_prec_get(tsd_tsdn(tsd), arena);
|
||||||
} else {
|
} else {
|
||||||
if (dss_prec != dss_prec_limit &&
|
if (dss_prec != dss_prec_limit &&
|
||||||
chunk_dss_prec_set(tsd_tsdn(tsd), dss_prec)) {
|
chunk_dss_prec_set(dss_prec)) {
|
||||||
ret = EFAULT;
|
ret = EFAULT;
|
||||||
goto label_return;
|
goto label_return;
|
||||||
}
|
}
|
||||||
dss_prec_old = chunk_dss_prec_get(tsd_tsdn(tsd));
|
dss_prec_old = chunk_dss_prec_get();
|
||||||
}
|
}
|
||||||
|
|
||||||
dss = dss_prec_names[dss_prec_old];
|
dss = dss_prec_names[dss_prec_old];
|
||||||
@@ -2100,7 +2100,7 @@ prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
|||||||
if (lg_sample >= (sizeof(uint64_t) << 3))
|
if (lg_sample >= (sizeof(uint64_t) << 3))
|
||||||
lg_sample = (sizeof(uint64_t) << 3) - 1;
|
lg_sample = (sizeof(uint64_t) << 3) - 1;
|
||||||
|
|
||||||
prof_reset(tsd_tsdn(tsd), lg_sample);
|
prof_reset(tsd, lg_sample);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
label_return:
|
label_return:
|
||||||
|
|||||||
78
src/extent.c
78
src/extent.c
@@ -3,42 +3,45 @@
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Round down to the nearest chunk size that can actually be requested during
|
||||||
|
* normal huge allocation.
|
||||||
|
*/
|
||||||
JEMALLOC_INLINE_C size_t
|
JEMALLOC_INLINE_C size_t
|
||||||
extent_quantize(size_t size)
|
extent_quantize(size_t size)
|
||||||
{
|
{
|
||||||
|
size_t ret;
|
||||||
|
szind_t ind;
|
||||||
|
|
||||||
/*
|
assert(size > 0);
|
||||||
* Round down to the nearest chunk size that can actually be requested
|
|
||||||
* during normal huge allocation.
|
|
||||||
*/
|
|
||||||
return (index2size(size2index(size + 1) - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_INLINE_C int
|
ind = size2index(size + 1);
|
||||||
extent_szad_comp(const extent_node_t *a, const extent_node_t *b)
|
if (ind == 0) {
|
||||||
{
|
/* Avoid underflow. */
|
||||||
int ret;
|
return (index2size(0));
|
||||||
size_t a_qsize = extent_quantize(extent_node_size_get(a));
|
|
||||||
size_t b_qsize = extent_quantize(extent_node_size_get(b));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compare based on quantized size rather than size, in order to sort
|
|
||||||
* equally useful extents only by address.
|
|
||||||
*/
|
|
||||||
ret = (a_qsize > b_qsize) - (a_qsize < b_qsize);
|
|
||||||
if (ret == 0) {
|
|
||||||
uintptr_t a_addr = (uintptr_t)extent_node_addr_get(a);
|
|
||||||
uintptr_t b_addr = (uintptr_t)extent_node_addr_get(b);
|
|
||||||
|
|
||||||
ret = (a_addr > b_addr) - (a_addr < b_addr);
|
|
||||||
}
|
}
|
||||||
|
ret = index2size(ind - 1);
|
||||||
|
assert(ret <= size);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate red-black tree functions. */
|
JEMALLOC_INLINE_C int
|
||||||
rb_gen(, extent_tree_szad_, extent_tree_t, extent_node_t, szad_link,
|
extent_sz_comp(const extent_node_t *a, const extent_node_t *b)
|
||||||
extent_szad_comp)
|
{
|
||||||
|
size_t a_qsize = extent_quantize(extent_node_size_get(a));
|
||||||
|
size_t b_qsize = extent_quantize(extent_node_size_get(b));
|
||||||
|
|
||||||
|
return ((a_qsize > b_qsize) - (a_qsize < b_qsize));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE_C int
|
||||||
|
extent_sn_comp(const extent_node_t *a, const extent_node_t *b)
|
||||||
|
{
|
||||||
|
size_t a_sn = extent_node_sn_get(a);
|
||||||
|
size_t b_sn = extent_node_sn_get(b);
|
||||||
|
|
||||||
|
return ((a_sn > b_sn) - (a_sn < b_sn));
|
||||||
|
}
|
||||||
|
|
||||||
JEMALLOC_INLINE_C int
|
JEMALLOC_INLINE_C int
|
||||||
extent_ad_comp(const extent_node_t *a, const extent_node_t *b)
|
extent_ad_comp(const extent_node_t *a, const extent_node_t *b)
|
||||||
@@ -49,5 +52,26 @@ extent_ad_comp(const extent_node_t *a, const extent_node_t *b)
|
|||||||
return ((a_addr > b_addr) - (a_addr < b_addr));
|
return ((a_addr > b_addr) - (a_addr < b_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE_C int
|
||||||
|
extent_szsnad_comp(const extent_node_t *a, const extent_node_t *b)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = extent_sz_comp(a, b);
|
||||||
|
if (ret != 0)
|
||||||
|
return (ret);
|
||||||
|
|
||||||
|
ret = extent_sn_comp(a, b);
|
||||||
|
if (ret != 0)
|
||||||
|
return (ret);
|
||||||
|
|
||||||
|
ret = extent_ad_comp(a, b);
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate red-black tree functions. */
|
||||||
|
rb_gen(, extent_tree_szsnad_, extent_tree_t, extent_node_t, szsnad_link,
|
||||||
|
extent_szsnad_comp)
|
||||||
|
|
||||||
/* Generate red-black tree functions. */
|
/* Generate red-black tree functions. */
|
||||||
rb_gen(, extent_tree_ad_, extent_tree_t, extent_node_t, ad_link, extent_ad_comp)
|
rb_gen(, extent_tree_ad_, extent_tree_t, extent_node_t, ad_link, extent_ad_comp)
|
||||||
|
|||||||
36
src/huge.c
36
src/huge.c
@@ -54,7 +54,9 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
|
|||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
size_t ausize;
|
size_t ausize;
|
||||||
|
arena_t *iarena;
|
||||||
extent_node_t *node;
|
extent_node_t *node;
|
||||||
|
size_t sn;
|
||||||
bool is_zeroed;
|
bool is_zeroed;
|
||||||
|
|
||||||
/* Allocate one or more contiguous chunks for this request. */
|
/* Allocate one or more contiguous chunks for this request. */
|
||||||
@@ -67,8 +69,10 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
|
|||||||
assert(ausize >= chunksize);
|
assert(ausize >= chunksize);
|
||||||
|
|
||||||
/* Allocate an extent node with which to track the chunk. */
|
/* Allocate an extent node with which to track the chunk. */
|
||||||
|
iarena = (!tsdn_null(tsdn)) ? arena_ichoose(tsdn_tsd(tsdn), NULL) :
|
||||||
|
a0get();
|
||||||
node = ipallocztm(tsdn, CACHELINE_CEILING(sizeof(extent_node_t)),
|
node = ipallocztm(tsdn, CACHELINE_CEILING(sizeof(extent_node_t)),
|
||||||
CACHELINE, false, NULL, true, arena_ichoose(tsdn, arena));
|
CACHELINE, false, NULL, true, iarena);
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
@@ -80,15 +84,15 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
|
|||||||
if (likely(!tsdn_null(tsdn)))
|
if (likely(!tsdn_null(tsdn)))
|
||||||
arena = arena_choose(tsdn_tsd(tsdn), arena);
|
arena = arena_choose(tsdn_tsd(tsdn), arena);
|
||||||
if (unlikely(arena == NULL) || (ret = arena_chunk_alloc_huge(tsdn,
|
if (unlikely(arena == NULL) || (ret = arena_chunk_alloc_huge(tsdn,
|
||||||
arena, usize, alignment, &is_zeroed)) == NULL) {
|
arena, usize, alignment, &sn, &is_zeroed)) == NULL) {
|
||||||
idalloctm(tsdn, node, NULL, true, true);
|
idalloctm(tsdn, node, NULL, true, true);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
extent_node_init(node, arena, ret, usize, is_zeroed, true);
|
extent_node_init(node, arena, ret, usize, sn, is_zeroed, true);
|
||||||
|
|
||||||
if (huge_node_set(tsdn, ret, node)) {
|
if (huge_node_set(tsdn, ret, node)) {
|
||||||
arena_chunk_dalloc_huge(tsdn, arena, ret, usize);
|
arena_chunk_dalloc_huge(tsdn, arena, ret, usize, sn);
|
||||||
idalloctm(tsdn, node, NULL, true, true);
|
idalloctm(tsdn, node, NULL, true, true);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@@ -114,7 +118,7 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
|
|||||||
#define huge_dalloc_junk JEMALLOC_N(huge_dalloc_junk_impl)
|
#define huge_dalloc_junk JEMALLOC_N(huge_dalloc_junk_impl)
|
||||||
#endif
|
#endif
|
||||||
static void
|
static void
|
||||||
huge_dalloc_junk(tsdn_t *tsdn, void *ptr, size_t usize)
|
huge_dalloc_junk(void *ptr, size_t usize)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (config_fill && have_dss && unlikely(opt_junk_free)) {
|
if (config_fill && have_dss && unlikely(opt_junk_free)) {
|
||||||
@@ -122,7 +126,7 @@ huge_dalloc_junk(tsdn_t *tsdn, void *ptr, size_t usize)
|
|||||||
* Only bother junk filling if the chunk isn't about to be
|
* Only bother junk filling if the chunk isn't about to be
|
||||||
* unmapped.
|
* unmapped.
|
||||||
*/
|
*/
|
||||||
if (!config_munmap || (have_dss && chunk_in_dss(tsdn, ptr)))
|
if (!config_munmap || (have_dss && chunk_in_dss(ptr)))
|
||||||
memset(ptr, JEMALLOC_FREE_JUNK, usize);
|
memset(ptr, JEMALLOC_FREE_JUNK, usize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,7 +225,7 @@ huge_ralloc_no_move_shrink(tsdn_t *tsdn, void *ptr, size_t oldsize,
|
|||||||
if (oldsize > usize) {
|
if (oldsize > usize) {
|
||||||
size_t sdiff = oldsize - usize;
|
size_t sdiff = oldsize - usize;
|
||||||
if (config_fill && unlikely(opt_junk_free)) {
|
if (config_fill && unlikely(opt_junk_free)) {
|
||||||
huge_dalloc_junk(tsdn, (void *)((uintptr_t)ptr + usize),
|
huge_dalloc_junk((void *)((uintptr_t)ptr + usize),
|
||||||
sdiff);
|
sdiff);
|
||||||
post_zeroed = false;
|
post_zeroed = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -243,7 +247,8 @@ huge_ralloc_no_move_shrink(tsdn_t *tsdn, void *ptr, size_t oldsize,
|
|||||||
malloc_mutex_unlock(tsdn, &arena->huge_mtx);
|
malloc_mutex_unlock(tsdn, &arena->huge_mtx);
|
||||||
|
|
||||||
/* Zap the excess chunks. */
|
/* Zap the excess chunks. */
|
||||||
arena_chunk_ralloc_huge_shrink(tsdn, arena, ptr, oldsize, usize);
|
arena_chunk_ralloc_huge_shrink(tsdn, arena, ptr, oldsize, usize,
|
||||||
|
extent_node_sn_get(node));
|
||||||
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
@@ -262,19 +267,19 @@ huge_ralloc_no_move_expand(tsdn_t *tsdn, void *ptr, size_t oldsize,
|
|||||||
malloc_mutex_unlock(tsdn, &arena->huge_mtx);
|
malloc_mutex_unlock(tsdn, &arena->huge_mtx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy zero into is_zeroed_chunk and pass the copy to chunk_alloc(), so
|
* Use is_zeroed_chunk to detect whether the trailing memory is zeroed,
|
||||||
* that it is possible to make correct junk/zero fill decisions below.
|
* update extent's zeroed field, and zero as necessary.
|
||||||
*/
|
*/
|
||||||
is_zeroed_chunk = zero;
|
is_zeroed_chunk = false;
|
||||||
|
|
||||||
if (arena_chunk_ralloc_huge_expand(tsdn, arena, ptr, oldsize, usize,
|
if (arena_chunk_ralloc_huge_expand(tsdn, arena, ptr, oldsize, usize,
|
||||||
&is_zeroed_chunk))
|
&is_zeroed_chunk))
|
||||||
return (true);
|
return (true);
|
||||||
|
|
||||||
malloc_mutex_lock(tsdn, &arena->huge_mtx);
|
malloc_mutex_lock(tsdn, &arena->huge_mtx);
|
||||||
/* Update the size of the huge allocation. */
|
|
||||||
huge_node_unset(ptr, node);
|
huge_node_unset(ptr, node);
|
||||||
extent_node_size_set(node, usize);
|
extent_node_size_set(node, usize);
|
||||||
|
extent_node_zeroed_set(node, extent_node_zeroed_get(node) &&
|
||||||
|
is_zeroed_chunk);
|
||||||
huge_node_reset(tsdn, ptr, node);
|
huge_node_reset(tsdn, ptr, node);
|
||||||
malloc_mutex_unlock(tsdn, &arena->huge_mtx);
|
malloc_mutex_unlock(tsdn, &arena->huge_mtx);
|
||||||
|
|
||||||
@@ -402,10 +407,11 @@ huge_dalloc(tsdn_t *tsdn, void *ptr)
|
|||||||
ql_remove(&arena->huge, node, ql_link);
|
ql_remove(&arena->huge, node, ql_link);
|
||||||
malloc_mutex_unlock(tsdn, &arena->huge_mtx);
|
malloc_mutex_unlock(tsdn, &arena->huge_mtx);
|
||||||
|
|
||||||
huge_dalloc_junk(tsdn, extent_node_addr_get(node),
|
huge_dalloc_junk(extent_node_addr_get(node),
|
||||||
extent_node_size_get(node));
|
extent_node_size_get(node));
|
||||||
arena_chunk_dalloc_huge(tsdn, extent_node_arena_get(node),
|
arena_chunk_dalloc_huge(tsdn, extent_node_arena_get(node),
|
||||||
extent_node_addr_get(node), extent_node_size_get(node));
|
extent_node_addr_get(node), extent_node_size_get(node),
|
||||||
|
extent_node_sn_get(node));
|
||||||
idalloctm(tsdn, node, NULL, true, true);
|
idalloctm(tsdn, node, NULL, true, true);
|
||||||
|
|
||||||
arena_decay_tick(tsdn, arena);
|
arena_decay_tick(tsdn, arena);
|
||||||
|
|||||||
209
src/jemalloc.c
209
src/jemalloc.c
@@ -5,7 +5,11 @@
|
|||||||
/* Data. */
|
/* Data. */
|
||||||
|
|
||||||
/* Runtime configuration options. */
|
/* Runtime configuration options. */
|
||||||
const char *je_malloc_conf JEMALLOC_ATTR(weak);
|
const char *je_malloc_conf
|
||||||
|
#ifndef _WIN32
|
||||||
|
JEMALLOC_ATTR(weak)
|
||||||
|
#endif
|
||||||
|
;
|
||||||
bool opt_abort =
|
bool opt_abort =
|
||||||
#ifdef JEMALLOC_DEBUG
|
#ifdef JEMALLOC_DEBUG
|
||||||
true
|
true
|
||||||
@@ -85,14 +89,25 @@ enum {
|
|||||||
};
|
};
|
||||||
static uint8_t malloc_slow_flags;
|
static uint8_t malloc_slow_flags;
|
||||||
|
|
||||||
/* Last entry for overflow detection only. */
|
|
||||||
JEMALLOC_ALIGNED(CACHELINE)
|
JEMALLOC_ALIGNED(CACHELINE)
|
||||||
const size_t index2size_tab[NSIZES+1] = {
|
const size_t pind2sz_tab[NPSIZES] = {
|
||||||
#define SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \
|
#define PSZ_yes(lg_grp, ndelta, lg_delta) \
|
||||||
|
(((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta))),
|
||||||
|
#define PSZ_no(lg_grp, ndelta, lg_delta)
|
||||||
|
#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, lg_delta_lookup) \
|
||||||
|
PSZ_##psz(lg_grp, ndelta, lg_delta)
|
||||||
|
SIZE_CLASSES
|
||||||
|
#undef PSZ_yes
|
||||||
|
#undef PSZ_no
|
||||||
|
#undef SC
|
||||||
|
};
|
||||||
|
|
||||||
|
JEMALLOC_ALIGNED(CACHELINE)
|
||||||
|
const size_t index2size_tab[NSIZES] = {
|
||||||
|
#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, lg_delta_lookup) \
|
||||||
((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta)),
|
((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta)),
|
||||||
SIZE_CLASSES
|
SIZE_CLASSES
|
||||||
#undef SC
|
#undef SC
|
||||||
ZU(0)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JEMALLOC_ALIGNED(CACHELINE)
|
JEMALLOC_ALIGNED(CACHELINE)
|
||||||
@@ -161,7 +176,7 @@ const uint8_t size2index_tab[] = {
|
|||||||
#define S2B_11(i) S2B_10(i) S2B_10(i)
|
#define S2B_11(i) S2B_10(i) S2B_10(i)
|
||||||
#endif
|
#endif
|
||||||
#define S2B_no(i)
|
#define S2B_no(i)
|
||||||
#define SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \
|
#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, lg_delta_lookup) \
|
||||||
S2B_##lg_delta_lookup(index)
|
S2B_##lg_delta_lookup(index)
|
||||||
SIZE_CLASSES
|
SIZE_CLASSES
|
||||||
#undef S2B_3
|
#undef S2B_3
|
||||||
@@ -329,6 +344,13 @@ a0idalloc(void *ptr, bool is_metadata)
|
|||||||
idalloctm(TSDN_NULL, ptr, false, is_metadata, true);
|
idalloctm(TSDN_NULL, ptr, false, is_metadata, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arena_t *
|
||||||
|
a0get(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (a0);
|
||||||
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
a0malloc(size_t size)
|
a0malloc(size_t size)
|
||||||
{
|
{
|
||||||
@@ -455,15 +477,16 @@ arena_bind(tsd_t *tsd, unsigned ind, bool internal)
|
|||||||
{
|
{
|
||||||
arena_t *arena;
|
arena_t *arena;
|
||||||
|
|
||||||
|
if (!tsd_nominal(tsd))
|
||||||
|
return;
|
||||||
|
|
||||||
arena = arena_get(tsd_tsdn(tsd), ind, false);
|
arena = arena_get(tsd_tsdn(tsd), ind, false);
|
||||||
arena_nthreads_inc(arena, internal);
|
arena_nthreads_inc(arena, internal);
|
||||||
|
|
||||||
if (tsd_nominal(tsd)) {
|
if (internal)
|
||||||
if (internal)
|
tsd_iarena_set(tsd, arena);
|
||||||
tsd_iarena_set(tsd, arena);
|
else
|
||||||
else
|
tsd_arena_set(tsd, arena);
|
||||||
tsd_arena_set(tsd, arena);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -789,6 +812,20 @@ malloc_ncpus(void)
|
|||||||
SYSTEM_INFO si;
|
SYSTEM_INFO si;
|
||||||
GetSystemInfo(&si);
|
GetSystemInfo(&si);
|
||||||
result = si.dwNumberOfProcessors;
|
result = si.dwNumberOfProcessors;
|
||||||
|
#elif defined(JEMALLOC_GLIBC_MALLOC_HOOK) && defined(CPU_COUNT)
|
||||||
|
/*
|
||||||
|
* glibc >= 2.6 has the CPU_COUNT macro.
|
||||||
|
*
|
||||||
|
* glibc's sysconf() uses isspace(). glibc allocates for the first time
|
||||||
|
* *before* setting up the isspace tables. Therefore we need a
|
||||||
|
* different method to get the number of CPUs.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
cpu_set_t set;
|
||||||
|
|
||||||
|
pthread_getaffinity_np(pthread_self(), sizeof(set), &set);
|
||||||
|
result = CPU_COUNT(&set);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
result = sysconf(_SC_NPROCESSORS_ONLN);
|
result = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
#endif
|
#endif
|
||||||
@@ -1019,7 +1056,11 @@ malloc_conf_init(void)
|
|||||||
if (cont) \
|
if (cont) \
|
||||||
continue; \
|
continue; \
|
||||||
}
|
}
|
||||||
#define CONF_HANDLE_T_U(t, o, n, min, max, clip) \
|
#define CONF_MIN_no(um, min) false
|
||||||
|
#define CONF_MIN_yes(um, min) ((um) < (min))
|
||||||
|
#define CONF_MAX_no(um, max) false
|
||||||
|
#define CONF_MAX_yes(um, max) ((um) > (max))
|
||||||
|
#define CONF_HANDLE_T_U(t, o, n, min, max, check_min, check_max, clip) \
|
||||||
if (CONF_MATCH(n)) { \
|
if (CONF_MATCH(n)) { \
|
||||||
uintmax_t um; \
|
uintmax_t um; \
|
||||||
char *end; \
|
char *end; \
|
||||||
@@ -1032,15 +1073,19 @@ malloc_conf_init(void)
|
|||||||
"Invalid conf value", \
|
"Invalid conf value", \
|
||||||
k, klen, v, vlen); \
|
k, klen, v, vlen); \
|
||||||
} else if (clip) { \
|
} else if (clip) { \
|
||||||
if ((min) != 0 && um < (min)) \
|
if (CONF_MIN_##check_min(um, \
|
||||||
|
(min))) \
|
||||||
o = (t)(min); \
|
o = (t)(min); \
|
||||||
else if (um > (max)) \
|
else if (CONF_MAX_##check_max( \
|
||||||
|
um, (max))) \
|
||||||
o = (t)(max); \
|
o = (t)(max); \
|
||||||
else \
|
else \
|
||||||
o = (t)um; \
|
o = (t)um; \
|
||||||
} else { \
|
} else { \
|
||||||
if (((min) != 0 && um < (min)) \
|
if (CONF_MIN_##check_min(um, \
|
||||||
|| um > (max)) { \
|
(min)) || \
|
||||||
|
CONF_MAX_##check_max(um, \
|
||||||
|
(max))) { \
|
||||||
malloc_conf_error( \
|
malloc_conf_error( \
|
||||||
"Out-of-range " \
|
"Out-of-range " \
|
||||||
"conf value", \
|
"conf value", \
|
||||||
@@ -1050,10 +1095,13 @@ malloc_conf_init(void)
|
|||||||
} \
|
} \
|
||||||
continue; \
|
continue; \
|
||||||
}
|
}
|
||||||
#define CONF_HANDLE_UNSIGNED(o, n, min, max, clip) \
|
#define CONF_HANDLE_UNSIGNED(o, n, min, max, check_min, check_max, \
|
||||||
CONF_HANDLE_T_U(unsigned, o, n, min, max, clip)
|
clip) \
|
||||||
#define CONF_HANDLE_SIZE_T(o, n, min, max, clip) \
|
CONF_HANDLE_T_U(unsigned, o, n, min, max, \
|
||||||
CONF_HANDLE_T_U(size_t, o, n, min, max, clip)
|
check_min, check_max, clip)
|
||||||
|
#define CONF_HANDLE_SIZE_T(o, n, min, max, check_min, check_max, clip) \
|
||||||
|
CONF_HANDLE_T_U(size_t, o, n, min, max, \
|
||||||
|
check_min, check_max, clip)
|
||||||
#define CONF_HANDLE_SSIZE_T(o, n, min, max) \
|
#define CONF_HANDLE_SSIZE_T(o, n, min, max) \
|
||||||
if (CONF_MATCH(n)) { \
|
if (CONF_MATCH(n)) { \
|
||||||
long l; \
|
long l; \
|
||||||
@@ -1096,15 +1144,14 @@ malloc_conf_init(void)
|
|||||||
*/
|
*/
|
||||||
CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE +
|
CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE +
|
||||||
LG_SIZE_CLASS_GROUP + (config_fill ? 2 : 1),
|
LG_SIZE_CLASS_GROUP + (config_fill ? 2 : 1),
|
||||||
(sizeof(size_t) << 3) - 1, true)
|
(sizeof(size_t) << 3) - 1, yes, yes, true)
|
||||||
if (strncmp("dss", k, klen) == 0) {
|
if (strncmp("dss", k, klen) == 0) {
|
||||||
int i;
|
int i;
|
||||||
bool match = false;
|
bool match = false;
|
||||||
for (i = 0; i < dss_prec_limit; i++) {
|
for (i = 0; i < dss_prec_limit; i++) {
|
||||||
if (strncmp(dss_prec_names[i], v, vlen)
|
if (strncmp(dss_prec_names[i], v, vlen)
|
||||||
== 0) {
|
== 0) {
|
||||||
if (chunk_dss_prec_set(NULL,
|
if (chunk_dss_prec_set(i)) {
|
||||||
i)) {
|
|
||||||
malloc_conf_error(
|
malloc_conf_error(
|
||||||
"Error setting dss",
|
"Error setting dss",
|
||||||
k, klen, v, vlen);
|
k, klen, v, vlen);
|
||||||
@@ -1123,7 +1170,7 @@ malloc_conf_init(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CONF_HANDLE_UNSIGNED(opt_narenas, "narenas", 1,
|
CONF_HANDLE_UNSIGNED(opt_narenas, "narenas", 1,
|
||||||
UINT_MAX, false)
|
UINT_MAX, yes, no, false)
|
||||||
if (strncmp("purge", k, klen) == 0) {
|
if (strncmp("purge", k, klen) == 0) {
|
||||||
int i;
|
int i;
|
||||||
bool match = false;
|
bool match = false;
|
||||||
@@ -1149,9 +1196,20 @@ malloc_conf_init(void)
|
|||||||
if (config_fill) {
|
if (config_fill) {
|
||||||
if (CONF_MATCH("junk")) {
|
if (CONF_MATCH("junk")) {
|
||||||
if (CONF_MATCH_VALUE("true")) {
|
if (CONF_MATCH_VALUE("true")) {
|
||||||
opt_junk = "true";
|
if (config_valgrind &&
|
||||||
opt_junk_alloc = opt_junk_free =
|
unlikely(in_valgrind)) {
|
||||||
true;
|
malloc_conf_error(
|
||||||
|
"Deallocation-time "
|
||||||
|
"junk filling cannot "
|
||||||
|
"be enabled while "
|
||||||
|
"running inside "
|
||||||
|
"Valgrind", k, klen, v,
|
||||||
|
vlen);
|
||||||
|
} else {
|
||||||
|
opt_junk = "true";
|
||||||
|
opt_junk_alloc = true;
|
||||||
|
opt_junk_free = true;
|
||||||
|
}
|
||||||
} else if (CONF_MATCH_VALUE("false")) {
|
} else if (CONF_MATCH_VALUE("false")) {
|
||||||
opt_junk = "false";
|
opt_junk = "false";
|
||||||
opt_junk_alloc = opt_junk_free =
|
opt_junk_alloc = opt_junk_free =
|
||||||
@@ -1161,9 +1219,20 @@ malloc_conf_init(void)
|
|||||||
opt_junk_alloc = true;
|
opt_junk_alloc = true;
|
||||||
opt_junk_free = false;
|
opt_junk_free = false;
|
||||||
} else if (CONF_MATCH_VALUE("free")) {
|
} else if (CONF_MATCH_VALUE("free")) {
|
||||||
opt_junk = "free";
|
if (config_valgrind &&
|
||||||
opt_junk_alloc = false;
|
unlikely(in_valgrind)) {
|
||||||
opt_junk_free = true;
|
malloc_conf_error(
|
||||||
|
"Deallocation-time "
|
||||||
|
"junk filling cannot "
|
||||||
|
"be enabled while "
|
||||||
|
"running inside "
|
||||||
|
"Valgrind", k, klen, v,
|
||||||
|
vlen);
|
||||||
|
} else {
|
||||||
|
opt_junk = "free";
|
||||||
|
opt_junk_alloc = false;
|
||||||
|
opt_junk_free = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
malloc_conf_error(
|
malloc_conf_error(
|
||||||
"Invalid conf value", k,
|
"Invalid conf value", k,
|
||||||
@@ -1172,7 +1241,7 @@ malloc_conf_init(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine",
|
CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine",
|
||||||
0, SIZE_T_MAX, false)
|
0, SIZE_T_MAX, no, no, false)
|
||||||
CONF_HANDLE_BOOL(opt_redzone, "redzone", true)
|
CONF_HANDLE_BOOL(opt_redzone, "redzone", true)
|
||||||
CONF_HANDLE_BOOL(opt_zero, "zero", true)
|
CONF_HANDLE_BOOL(opt_zero, "zero", true)
|
||||||
}
|
}
|
||||||
@@ -1209,8 +1278,8 @@ malloc_conf_init(void)
|
|||||||
CONF_HANDLE_BOOL(opt_prof_thread_active_init,
|
CONF_HANDLE_BOOL(opt_prof_thread_active_init,
|
||||||
"prof_thread_active_init", true)
|
"prof_thread_active_init", true)
|
||||||
CONF_HANDLE_SIZE_T(opt_lg_prof_sample,
|
CONF_HANDLE_SIZE_T(opt_lg_prof_sample,
|
||||||
"lg_prof_sample", 0,
|
"lg_prof_sample", 0, (sizeof(uint64_t) << 3)
|
||||||
(sizeof(uint64_t) << 3) - 1, true)
|
- 1, no, yes, true)
|
||||||
CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum",
|
CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum",
|
||||||
true)
|
true)
|
||||||
CONF_HANDLE_SSIZE_T(opt_lg_prof_interval,
|
CONF_HANDLE_SSIZE_T(opt_lg_prof_interval,
|
||||||
@@ -1226,7 +1295,14 @@ malloc_conf_init(void)
|
|||||||
malloc_conf_error("Invalid conf pair", k, klen, v,
|
malloc_conf_error("Invalid conf pair", k, klen, v,
|
||||||
vlen);
|
vlen);
|
||||||
#undef CONF_MATCH
|
#undef CONF_MATCH
|
||||||
|
#undef CONF_MATCH_VALUE
|
||||||
#undef CONF_HANDLE_BOOL
|
#undef CONF_HANDLE_BOOL
|
||||||
|
#undef CONF_MIN_no
|
||||||
|
#undef CONF_MIN_yes
|
||||||
|
#undef CONF_MAX_no
|
||||||
|
#undef CONF_MAX_yes
|
||||||
|
#undef CONF_HANDLE_T_U
|
||||||
|
#undef CONF_HANDLE_UNSIGNED
|
||||||
#undef CONF_HANDLE_SIZE_T
|
#undef CONF_HANDLE_SIZE_T
|
||||||
#undef CONF_HANDLE_SSIZE_T
|
#undef CONF_HANDLE_SSIZE_T
|
||||||
#undef CONF_HANDLE_CHAR_P
|
#undef CONF_HANDLE_CHAR_P
|
||||||
@@ -1249,11 +1325,14 @@ malloc_init_hard_needed(void)
|
|||||||
}
|
}
|
||||||
#ifdef JEMALLOC_THREADED_INIT
|
#ifdef JEMALLOC_THREADED_INIT
|
||||||
if (malloc_initializer != NO_INITIALIZER && !IS_INITIALIZER) {
|
if (malloc_initializer != NO_INITIALIZER && !IS_INITIALIZER) {
|
||||||
|
spin_t spinner;
|
||||||
|
|
||||||
/* Busy-wait until the initializing thread completes. */
|
/* Busy-wait until the initializing thread completes. */
|
||||||
|
spin_init(&spinner);
|
||||||
do {
|
do {
|
||||||
malloc_mutex_unlock(NULL, &init_lock);
|
malloc_mutex_unlock(TSDN_NULL, &init_lock);
|
||||||
CPU_SPINWAIT;
|
spin_adaptive(&spinner);
|
||||||
malloc_mutex_lock(NULL, &init_lock);
|
malloc_mutex_lock(TSDN_NULL, &init_lock);
|
||||||
} while (!malloc_initialized());
|
} while (!malloc_initialized());
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
@@ -1287,8 +1366,7 @@ malloc_init_hard_a0_locked()
|
|||||||
return (true);
|
return (true);
|
||||||
if (config_prof)
|
if (config_prof)
|
||||||
prof_boot1();
|
prof_boot1();
|
||||||
if (arena_boot())
|
arena_boot();
|
||||||
return (true);
|
|
||||||
if (config_tcache && tcache_boot(TSDN_NULL))
|
if (config_tcache && tcache_boot(TSDN_NULL))
|
||||||
return (true);
|
return (true);
|
||||||
if (malloc_mutex_init(&arenas_lock, "arenas", WITNESS_RANK_ARENAS))
|
if (malloc_mutex_init(&arenas_lock, "arenas", WITNESS_RANK_ARENAS))
|
||||||
@@ -1333,8 +1411,9 @@ malloc_init_hard_recursible(void)
|
|||||||
|
|
||||||
ncpus = malloc_ncpus();
|
ncpus = malloc_ncpus();
|
||||||
|
|
||||||
#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \
|
#if (defined(JEMALLOC_HAVE_PTHREAD_ATFORK) && !defined(JEMALLOC_MUTEX_INIT_CB) \
|
||||||
&& !defined(_WIN32) && !defined(__native_client__))
|
&& !defined(JEMALLOC_ZONE) && !defined(_WIN32) && \
|
||||||
|
!defined(__native_client__))
|
||||||
/* LinuxThreads' pthread_atfork() allocates. */
|
/* LinuxThreads' pthread_atfork() allocates. */
|
||||||
if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,
|
if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,
|
||||||
jemalloc_postfork_child) != 0) {
|
jemalloc_postfork_child) != 0) {
|
||||||
@@ -1419,7 +1498,7 @@ malloc_init_hard(void)
|
|||||||
return (true);
|
return (true);
|
||||||
malloc_mutex_lock(tsd_tsdn(tsd), &init_lock);
|
malloc_mutex_lock(tsd_tsdn(tsd), &init_lock);
|
||||||
|
|
||||||
if (config_prof && prof_boot2(tsd_tsdn(tsd))) {
|
if (config_prof && prof_boot2(tsd)) {
|
||||||
malloc_mutex_unlock(tsd_tsdn(tsd), &init_lock);
|
malloc_mutex_unlock(tsd_tsdn(tsd), &init_lock);
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
@@ -1739,7 +1818,7 @@ je_calloc(size_t num, size_t size)
|
|||||||
ret = ialloc_body(num_size, true, &tsdn, &usize, true);
|
ret = ialloc_body(num_size, true, &tsdn, &usize, true);
|
||||||
ialloc_post_check(ret, tsdn, usize, "calloc", true, true);
|
ialloc_post_check(ret, tsdn, usize, "calloc", true, true);
|
||||||
UTRACE(0, num_size, ret);
|
UTRACE(0, num_size, ret);
|
||||||
JEMALLOC_VALGRIND_MALLOC(ret != NULL, tsdn, ret, usize, false);
|
JEMALLOC_VALGRIND_MALLOC(ret != NULL, tsdn, ret, usize, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -1913,8 +1992,8 @@ je_realloc(void *ptr, size_t size)
|
|||||||
*tsd_thread_deallocatedp_get(tsd) += old_usize;
|
*tsd_thread_deallocatedp_get(tsd) += old_usize;
|
||||||
}
|
}
|
||||||
UTRACE(ptr, size, ret);
|
UTRACE(ptr, size, ret);
|
||||||
JEMALLOC_VALGRIND_REALLOC(true, tsdn, ret, usize, true, ptr, old_usize,
|
JEMALLOC_VALGRIND_REALLOC(maybe, tsdn, ret, usize, maybe, ptr,
|
||||||
old_rzsize, true, false);
|
old_usize, old_rzsize, maybe, false);
|
||||||
witness_assert_lockless(tsdn);
|
witness_assert_lockless(tsdn);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
@@ -1994,6 +2073,29 @@ JEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc;
|
|||||||
JEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) =
|
JEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) =
|
||||||
je_memalign;
|
je_memalign;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
#ifdef CPU_COUNT
|
||||||
|
/*
|
||||||
|
* To enable static linking with glibc, the libc specific malloc interface must
|
||||||
|
* be implemented also, so none of glibc's malloc.o functions are added to the
|
||||||
|
* link.
|
||||||
|
*/
|
||||||
|
#define ALIAS(je_fn) __attribute__((alias (#je_fn), used))
|
||||||
|
/* To force macro expansion of je_ prefix before stringification. */
|
||||||
|
#define PREALIAS(je_fn) ALIAS(je_fn)
|
||||||
|
void *__libc_malloc(size_t size) PREALIAS(je_malloc);
|
||||||
|
void __libc_free(void* ptr) PREALIAS(je_free);
|
||||||
|
void *__libc_realloc(void* ptr, size_t size) PREALIAS(je_realloc);
|
||||||
|
void *__libc_calloc(size_t n, size_t size) PREALIAS(je_calloc);
|
||||||
|
void *__libc_memalign(size_t align, size_t s) PREALIAS(je_memalign);
|
||||||
|
void *__libc_valloc(size_t size) PREALIAS(je_valloc);
|
||||||
|
int __posix_memalign(void** r, size_t a, size_t s)
|
||||||
|
PREALIAS(je_posix_memalign);
|
||||||
|
#undef PREALIAS
|
||||||
|
#undef ALIAS
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2222,7 +2324,7 @@ irallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size,
|
|||||||
|
|
||||||
prof_active = prof_active_get_unlocked();
|
prof_active = prof_active_get_unlocked();
|
||||||
old_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr);
|
old_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr);
|
||||||
tctx = prof_alloc_prep(tsd, *usize, prof_active, true);
|
tctx = prof_alloc_prep(tsd, *usize, prof_active, false);
|
||||||
if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {
|
if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {
|
||||||
p = irallocx_prof_sample(tsd, old_ptr, old_usize, *usize,
|
p = irallocx_prof_sample(tsd, old_ptr, old_usize, *usize,
|
||||||
alignment, zero, tcache, arena, tctx);
|
alignment, zero, tcache, arena, tctx);
|
||||||
@@ -2231,7 +2333,7 @@ irallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size,
|
|||||||
tcache, arena);
|
tcache, arena);
|
||||||
}
|
}
|
||||||
if (unlikely(p == NULL)) {
|
if (unlikely(p == NULL)) {
|
||||||
prof_alloc_rollback(tsd, tctx, true);
|
prof_alloc_rollback(tsd, tctx, false);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2246,7 +2348,7 @@ irallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size,
|
|||||||
*/
|
*/
|
||||||
*usize = isalloc(tsd_tsdn(tsd), p, config_prof);
|
*usize = isalloc(tsd_tsdn(tsd), p, config_prof);
|
||||||
}
|
}
|
||||||
prof_realloc(tsd, p, *usize, tctx, prof_active, true, old_ptr,
|
prof_realloc(tsd, p, *usize, tctx, prof_active, false, old_ptr,
|
||||||
old_usize, old_tctx);
|
old_usize, old_tctx);
|
||||||
|
|
||||||
return (p);
|
return (p);
|
||||||
@@ -2317,8 +2419,8 @@ je_rallocx(void *ptr, size_t size, int flags)
|
|||||||
*tsd_thread_deallocatedp_get(tsd) += old_usize;
|
*tsd_thread_deallocatedp_get(tsd) += old_usize;
|
||||||
}
|
}
|
||||||
UTRACE(ptr, size, p);
|
UTRACE(ptr, size, p);
|
||||||
JEMALLOC_VALGRIND_REALLOC(true, tsd_tsdn(tsd), p, usize, false, ptr,
|
JEMALLOC_VALGRIND_REALLOC(maybe, tsd_tsdn(tsd), p, usize, no, ptr,
|
||||||
old_usize, old_rzsize, false, zero);
|
old_usize, old_rzsize, no, zero);
|
||||||
witness_assert_lockless(tsd_tsdn(tsd));
|
witness_assert_lockless(tsd_tsdn(tsd));
|
||||||
return (p);
|
return (p);
|
||||||
label_oom:
|
label_oom:
|
||||||
@@ -2460,8 +2562,8 @@ je_xallocx(void *ptr, size_t size, size_t extra, int flags)
|
|||||||
*tsd_thread_allocatedp_get(tsd) += usize;
|
*tsd_thread_allocatedp_get(tsd) += usize;
|
||||||
*tsd_thread_deallocatedp_get(tsd) += old_usize;
|
*tsd_thread_deallocatedp_get(tsd) += old_usize;
|
||||||
}
|
}
|
||||||
JEMALLOC_VALGRIND_REALLOC(false, tsd_tsdn(tsd), ptr, usize, false, ptr,
|
JEMALLOC_VALGRIND_REALLOC(no, tsd_tsdn(tsd), ptr, usize, no, ptr,
|
||||||
old_usize, old_rzsize, false, zero);
|
old_usize, old_rzsize, no, zero);
|
||||||
label_not_resized:
|
label_not_resized:
|
||||||
UTRACE(ptr, size, ptr);
|
UTRACE(ptr, size, ptr);
|
||||||
witness_assert_lockless(tsd_tsdn(tsd));
|
witness_assert_lockless(tsd_tsdn(tsd));
|
||||||
@@ -2747,7 +2849,6 @@ _malloc_prefork(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
base_prefork(tsd_tsdn(tsd));
|
base_prefork(tsd_tsdn(tsd));
|
||||||
chunk_prefork(tsd_tsdn(tsd));
|
|
||||||
for (i = 0; i < narenas; i++) {
|
for (i = 0; i < narenas; i++) {
|
||||||
if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)
|
if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)
|
||||||
arena_prefork3(tsd_tsdn(tsd), arena);
|
arena_prefork3(tsd_tsdn(tsd), arena);
|
||||||
@@ -2776,7 +2877,6 @@ _malloc_postfork(void)
|
|||||||
|
|
||||||
witness_postfork_parent(tsd);
|
witness_postfork_parent(tsd);
|
||||||
/* Release all mutexes, now that fork() has completed. */
|
/* Release all mutexes, now that fork() has completed. */
|
||||||
chunk_postfork_parent(tsd_tsdn(tsd));
|
|
||||||
base_postfork_parent(tsd_tsdn(tsd));
|
base_postfork_parent(tsd_tsdn(tsd));
|
||||||
for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
|
for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
|
||||||
arena_t *arena;
|
arena_t *arena;
|
||||||
@@ -2801,7 +2901,6 @@ jemalloc_postfork_child(void)
|
|||||||
|
|
||||||
witness_postfork_child(tsd);
|
witness_postfork_child(tsd);
|
||||||
/* Release all mutexes, now that fork() has completed. */
|
/* Release all mutexes, now that fork() has completed. */
|
||||||
chunk_postfork_child(tsd_tsdn(tsd));
|
|
||||||
base_postfork_child(tsd_tsdn(tsd));
|
base_postfork_child(tsd_tsdn(tsd));
|
||||||
for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
|
for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
|
||||||
arena_t *arena;
|
arena_t *arena;
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ malloc_mutex_init(malloc_mutex_t *mutex, const char *name, witness_rank_t rank)
|
|||||||
_CRT_SPINCOUNT))
|
_CRT_SPINCOUNT))
|
||||||
return (true);
|
return (true);
|
||||||
# endif
|
# endif
|
||||||
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
||||||
|
mutex->lock = OS_UNFAIR_LOCK_INIT;
|
||||||
#elif (defined(JEMALLOC_OSSPIN))
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
mutex->lock = 0;
|
mutex->lock = 0;
|
||||||
#elif (defined(JEMALLOC_MUTEX_INIT_CB))
|
#elif (defined(JEMALLOC_MUTEX_INIT_CB))
|
||||||
|
|||||||
96
src/nstime.c
96
src/nstime.c
@@ -97,6 +97,76 @@ nstime_divide(const nstime_t *time, const nstime_t *divisor)
|
|||||||
return (time->ns / divisor->ns);
|
return (time->ns / divisor->ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define NSTIME_MONOTONIC true
|
||||||
|
static void
|
||||||
|
nstime_get(nstime_t *time)
|
||||||
|
{
|
||||||
|
FILETIME ft;
|
||||||
|
uint64_t ticks_100ns;
|
||||||
|
|
||||||
|
GetSystemTimeAsFileTime(&ft);
|
||||||
|
ticks_100ns = (((uint64_t)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||||
|
|
||||||
|
nstime_init(time, ticks_100ns * 100);
|
||||||
|
}
|
||||||
|
#elif JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE
|
||||||
|
# define NSTIME_MONOTONIC true
|
||||||
|
static void
|
||||||
|
nstime_get(nstime_t *time)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
|
||||||
|
nstime_init2(time, ts.tv_sec, ts.tv_nsec);
|
||||||
|
}
|
||||||
|
#elif JEMALLOC_HAVE_CLOCK_MONOTONIC
|
||||||
|
# define NSTIME_MONOTONIC true
|
||||||
|
static void
|
||||||
|
nstime_get(nstime_t *time)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
nstime_init2(time, ts.tv_sec, ts.tv_nsec);
|
||||||
|
}
|
||||||
|
#elif JEMALLOC_HAVE_MACH_ABSOLUTE_TIME
|
||||||
|
# define NSTIME_MONOTONIC true
|
||||||
|
static void
|
||||||
|
nstime_get(nstime_t *time)
|
||||||
|
{
|
||||||
|
|
||||||
|
nstime_init(time, mach_absolute_time());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define NSTIME_MONOTONIC false
|
||||||
|
static void
|
||||||
|
nstime_get(nstime_t *time)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
nstime_init2(time, tv.tv_sec, tv.tv_usec * 1000);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_JET
|
||||||
|
#undef nstime_monotonic
|
||||||
|
#define nstime_monotonic JEMALLOC_N(n_nstime_monotonic)
|
||||||
|
#endif
|
||||||
|
bool
|
||||||
|
nstime_monotonic(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (NSTIME_MONOTONIC);
|
||||||
|
#undef NSTIME_MONOTONIC
|
||||||
|
}
|
||||||
|
#ifdef JEMALLOC_JET
|
||||||
|
#undef nstime_monotonic
|
||||||
|
#define nstime_monotonic JEMALLOC_N(nstime_monotonic)
|
||||||
|
nstime_monotonic_t *nstime_monotonic = JEMALLOC_N(n_nstime_monotonic);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef JEMALLOC_JET
|
#ifdef JEMALLOC_JET
|
||||||
#undef nstime_update
|
#undef nstime_update
|
||||||
#define nstime_update JEMALLOC_N(n_nstime_update)
|
#define nstime_update JEMALLOC_N(n_nstime_update)
|
||||||
@@ -107,31 +177,7 @@ nstime_update(nstime_t *time)
|
|||||||
nstime_t old_time;
|
nstime_t old_time;
|
||||||
|
|
||||||
nstime_copy(&old_time, time);
|
nstime_copy(&old_time, time);
|
||||||
|
nstime_get(time);
|
||||||
#ifdef _WIN32
|
|
||||||
{
|
|
||||||
FILETIME ft;
|
|
||||||
uint64_t ticks;
|
|
||||||
GetSystemTimeAsFileTime(&ft);
|
|
||||||
ticks = (((uint64_t)ft.dwHighDateTime) << 32) |
|
|
||||||
ft.dwLowDateTime;
|
|
||||||
time->ns = ticks * 100;
|
|
||||||
}
|
|
||||||
#elif JEMALLOC_CLOCK_GETTIME
|
|
||||||
{
|
|
||||||
struct timespec ts;
|
|
||||||
|
|
||||||
if (sysconf(_SC_MONOTONIC_CLOCK) > 0)
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
||||||
else
|
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
|
||||||
time->ns = ts.tv_sec * BILLION + ts.tv_nsec;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
time->ns = tv.tv_sec * BILLION + tv.tv_usec * 1000;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Handle non-monotonic clocks. */
|
/* Handle non-monotonic clocks. */
|
||||||
if (unlikely(nstime_compare(&old_time, time) > 0)) {
|
if (unlikely(nstime_compare(&old_time, time) > 0)) {
|
||||||
|
|||||||
61
src/pages.c
61
src/pages.c
@@ -170,15 +170,16 @@ pages_purge(void *addr, size_t size)
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE);
|
VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE);
|
||||||
unzeroed = true;
|
unzeroed = true;
|
||||||
#elif defined(JEMALLOC_HAVE_MADVISE)
|
#elif (defined(JEMALLOC_PURGE_MADVISE_FREE) || \
|
||||||
# ifdef JEMALLOC_PURGE_MADVISE_DONTNEED
|
defined(JEMALLOC_PURGE_MADVISE_DONTNEED))
|
||||||
# define JEMALLOC_MADV_PURGE MADV_DONTNEED
|
# if defined(JEMALLOC_PURGE_MADVISE_FREE)
|
||||||
# define JEMALLOC_MADV_ZEROS true
|
|
||||||
# elif defined(JEMALLOC_PURGE_MADVISE_FREE)
|
|
||||||
# define JEMALLOC_MADV_PURGE MADV_FREE
|
# define JEMALLOC_MADV_PURGE MADV_FREE
|
||||||
# define JEMALLOC_MADV_ZEROS false
|
# define JEMALLOC_MADV_ZEROS false
|
||||||
|
# elif defined(JEMALLOC_PURGE_MADVISE_DONTNEED)
|
||||||
|
# define JEMALLOC_MADV_PURGE MADV_DONTNEED
|
||||||
|
# define JEMALLOC_MADV_ZEROS true
|
||||||
# else
|
# else
|
||||||
# error "No madvise(2) flag defined for purging unused dirty pages."
|
# error No madvise(2) flag defined for purging unused dirty pages
|
||||||
# endif
|
# endif
|
||||||
int err = madvise(addr, size, JEMALLOC_MADV_PURGE);
|
int err = madvise(addr, size, JEMALLOC_MADV_PURGE);
|
||||||
unzeroed = (!JEMALLOC_MADV_ZEROS || err != 0);
|
unzeroed = (!JEMALLOC_MADV_ZEROS || err != 0);
|
||||||
@@ -191,6 +192,34 @@ pages_purge(void *addr, size_t size)
|
|||||||
return (unzeroed);
|
return (unzeroed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pages_huge(void *addr, size_t size)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(PAGE_ADDR2BASE(addr) == addr);
|
||||||
|
assert(PAGE_CEILING(size) == size);
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_THP
|
||||||
|
return (madvise(addr, size, MADV_HUGEPAGE) != 0);
|
||||||
|
#else
|
||||||
|
return (false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pages_nohuge(void *addr, size_t size)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(PAGE_ADDR2BASE(addr) == addr);
|
||||||
|
assert(PAGE_CEILING(size) == size);
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_THP
|
||||||
|
return (madvise(addr, size, MADV_NOHUGEPAGE) != 0);
|
||||||
|
#else
|
||||||
|
return (false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT
|
#ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT
|
||||||
static bool
|
static bool
|
||||||
os_overcommits_sysctl(void)
|
os_overcommits_sysctl(void)
|
||||||
@@ -207,6 +236,11 @@ os_overcommits_sysctl(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY
|
#ifdef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY
|
||||||
|
/*
|
||||||
|
* Use syscall(2) rather than {open,read,close}(2) when possible to avoid
|
||||||
|
* reentry during bootstrapping if another library has interposed system call
|
||||||
|
* wrappers.
|
||||||
|
*/
|
||||||
static bool
|
static bool
|
||||||
os_overcommits_proc(void)
|
os_overcommits_proc(void)
|
||||||
{
|
{
|
||||||
@@ -214,11 +248,26 @@ os_overcommits_proc(void)
|
|||||||
char buf[1];
|
char buf[1];
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
|
|
||||||
|
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_open)
|
||||||
|
fd = (int)syscall(SYS_open, "/proc/sys/vm/overcommit_memory", O_RDONLY);
|
||||||
|
#else
|
||||||
fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY);
|
fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY);
|
||||||
|
#endif
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return (false); /* Error. */
|
return (false); /* Error. */
|
||||||
|
|
||||||
|
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read)
|
||||||
|
nread = (ssize_t)syscall(SYS_read, fd, &buf, sizeof(buf));
|
||||||
|
#else
|
||||||
nread = read(fd, &buf, sizeof(buf));
|
nread = read(fd, &buf, sizeof(buf));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_close)
|
||||||
|
syscall(SYS_close, fd);
|
||||||
|
#else
|
||||||
|
close(fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (nread < 1)
|
if (nread < 1)
|
||||||
return (false); /* Error. */
|
return (false); /* Error. */
|
||||||
/*
|
/*
|
||||||
|
|||||||
87
src/prof.c
87
src/prof.c
@@ -125,7 +125,7 @@ static bool prof_tctx_should_destroy(tsdn_t *tsdn, prof_tctx_t *tctx);
|
|||||||
static void prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx);
|
static void prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx);
|
||||||
static bool prof_tdata_should_destroy(tsdn_t *tsdn, prof_tdata_t *tdata,
|
static bool prof_tdata_should_destroy(tsdn_t *tsdn, prof_tdata_t *tdata,
|
||||||
bool even_if_attached);
|
bool even_if_attached);
|
||||||
static void prof_tdata_destroy(tsdn_t *tsdn, prof_tdata_t *tdata,
|
static void prof_tdata_destroy(tsd_t *tsd, prof_tdata_t *tdata,
|
||||||
bool even_if_attached);
|
bool even_if_attached);
|
||||||
static char *prof_thread_name_alloc(tsdn_t *tsdn, const char *thread_name);
|
static char *prof_thread_name_alloc(tsdn_t *tsdn, const char *thread_name);
|
||||||
|
|
||||||
@@ -591,7 +591,7 @@ prof_gctx_try_destroy(tsd_t *tsd, prof_tdata_t *tdata_self, prof_gctx_t *gctx,
|
|||||||
assert(gctx->nlimbo != 0);
|
assert(gctx->nlimbo != 0);
|
||||||
if (tctx_tree_empty(&gctx->tctxs) && gctx->nlimbo == 1) {
|
if (tctx_tree_empty(&gctx->tctxs) && gctx->nlimbo == 1) {
|
||||||
/* Remove gctx from bt2gctx. */
|
/* Remove gctx from bt2gctx. */
|
||||||
if (ckh_remove(tsd_tsdn(tsd), &bt2gctx, &gctx->bt, NULL, NULL))
|
if (ckh_remove(tsd, &bt2gctx, &gctx->bt, NULL, NULL))
|
||||||
not_reached();
|
not_reached();
|
||||||
prof_leave(tsd, tdata_self);
|
prof_leave(tsd, tdata_self);
|
||||||
/* Destroy gctx. */
|
/* Destroy gctx. */
|
||||||
@@ -651,7 +651,7 @@ prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx)
|
|||||||
assert(tctx->cnts.accumobjs == 0);
|
assert(tctx->cnts.accumobjs == 0);
|
||||||
assert(tctx->cnts.accumbytes == 0);
|
assert(tctx->cnts.accumbytes == 0);
|
||||||
|
|
||||||
ckh_remove(tsd_tsdn(tsd), &tdata->bt2tctx, &gctx->bt, NULL, NULL);
|
ckh_remove(tsd, &tdata->bt2tctx, &gctx->bt, NULL, NULL);
|
||||||
destroy_tdata = prof_tdata_should_destroy(tsd_tsdn(tsd), tdata, false);
|
destroy_tdata = prof_tdata_should_destroy(tsd_tsdn(tsd), tdata, false);
|
||||||
malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);
|
malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);
|
||||||
|
|
||||||
@@ -704,7 +704,7 @@ prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx)
|
|||||||
malloc_mutex_assert_not_owner(tsd_tsdn(tsd), tctx->tdata->lock);
|
malloc_mutex_assert_not_owner(tsd_tsdn(tsd), tctx->tdata->lock);
|
||||||
|
|
||||||
if (destroy_tdata)
|
if (destroy_tdata)
|
||||||
prof_tdata_destroy(tsd_tsdn(tsd), tdata, false);
|
prof_tdata_destroy(tsd, tdata, false);
|
||||||
|
|
||||||
if (destroy_tctx)
|
if (destroy_tctx)
|
||||||
idalloctm(tsd_tsdn(tsd), tctx, NULL, true, true);
|
idalloctm(tsd_tsdn(tsd), tctx, NULL, true, true);
|
||||||
@@ -733,7 +733,7 @@ prof_lookup_global(tsd_t *tsd, prof_bt_t *bt, prof_tdata_t *tdata,
|
|||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
btkey.p = &gctx.p->bt;
|
btkey.p = &gctx.p->bt;
|
||||||
if (ckh_insert(tsd_tsdn(tsd), &bt2gctx, btkey.v, gctx.v)) {
|
if (ckh_insert(tsd, &bt2gctx, btkey.v, gctx.v)) {
|
||||||
/* OOM. */
|
/* OOM. */
|
||||||
prof_leave(tsd, tdata);
|
prof_leave(tsd, tdata);
|
||||||
idalloctm(tsd_tsdn(tsd), gctx.v, NULL, true, true);
|
idalloctm(tsd_tsdn(tsd), gctx.v, NULL, true, true);
|
||||||
@@ -795,7 +795,7 @@ prof_lookup(tsd_t *tsd, prof_bt_t *bt)
|
|||||||
/* Link a prof_tctx_t into gctx for this thread. */
|
/* Link a prof_tctx_t into gctx for this thread. */
|
||||||
ret.v = iallocztm(tsd_tsdn(tsd), sizeof(prof_tctx_t),
|
ret.v = iallocztm(tsd_tsdn(tsd), sizeof(prof_tctx_t),
|
||||||
size2index(sizeof(prof_tctx_t)), false, NULL, true,
|
size2index(sizeof(prof_tctx_t)), false, NULL, true,
|
||||||
arena_ichoose(tsd_tsdn(tsd), NULL), true);
|
arena_ichoose(tsd, NULL), true);
|
||||||
if (ret.p == NULL) {
|
if (ret.p == NULL) {
|
||||||
if (new_gctx)
|
if (new_gctx)
|
||||||
prof_gctx_try_destroy(tsd, tdata, gctx, tdata);
|
prof_gctx_try_destroy(tsd, tdata, gctx, tdata);
|
||||||
@@ -810,8 +810,7 @@ prof_lookup(tsd_t *tsd, prof_bt_t *bt)
|
|||||||
ret.p->prepared = true;
|
ret.p->prepared = true;
|
||||||
ret.p->state = prof_tctx_state_initializing;
|
ret.p->state = prof_tctx_state_initializing;
|
||||||
malloc_mutex_lock(tsd_tsdn(tsd), tdata->lock);
|
malloc_mutex_lock(tsd_tsdn(tsd), tdata->lock);
|
||||||
error = ckh_insert(tsd_tsdn(tsd), &tdata->bt2tctx, btkey,
|
error = ckh_insert(tsd, &tdata->bt2tctx, btkey, ret.v);
|
||||||
ret.v);
|
|
||||||
malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);
|
malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);
|
||||||
if (error) {
|
if (error) {
|
||||||
if (new_gctx)
|
if (new_gctx)
|
||||||
@@ -875,7 +874,7 @@ prof_sample_threshold_update(prof_tdata_t *tdata)
|
|||||||
* pp 500
|
* pp 500
|
||||||
* (http://luc.devroye.org/rnbookindex.html)
|
* (http://luc.devroye.org/rnbookindex.html)
|
||||||
*/
|
*/
|
||||||
r = prng_lg_range(&tdata->prng_state, 53);
|
r = prng_lg_range_u64(&tdata->prng_state, 53);
|
||||||
u = (double)r * (1.0/9007199254740992.0L);
|
u = (double)r * (1.0/9007199254740992.0L);
|
||||||
tdata->bytes_until_sample = (uint64_t)(log(u) /
|
tdata->bytes_until_sample = (uint64_t)(log(u) /
|
||||||
log(1.0 - (1.0 / (double)((uint64_t)1U << lg_prof_sample))))
|
log(1.0 - (1.0 / (double)((uint64_t)1U << lg_prof_sample))))
|
||||||
@@ -1791,7 +1790,7 @@ prof_thr_uid_alloc(tsdn_t *tsdn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static prof_tdata_t *
|
static prof_tdata_t *
|
||||||
prof_tdata_init_impl(tsdn_t *tsdn, uint64_t thr_uid, uint64_t thr_discrim,
|
prof_tdata_init_impl(tsd_t *tsd, uint64_t thr_uid, uint64_t thr_discrim,
|
||||||
char *thread_name, bool active)
|
char *thread_name, bool active)
|
||||||
{
|
{
|
||||||
prof_tdata_t *tdata;
|
prof_tdata_t *tdata;
|
||||||
@@ -1799,7 +1798,7 @@ prof_tdata_init_impl(tsdn_t *tsdn, uint64_t thr_uid, uint64_t thr_discrim,
|
|||||||
cassert(config_prof);
|
cassert(config_prof);
|
||||||
|
|
||||||
/* Initialize an empty cache for this thread. */
|
/* Initialize an empty cache for this thread. */
|
||||||
tdata = (prof_tdata_t *)iallocztm(tsdn, sizeof(prof_tdata_t),
|
tdata = (prof_tdata_t *)iallocztm(tsd_tsdn(tsd), sizeof(prof_tdata_t),
|
||||||
size2index(sizeof(prof_tdata_t)), false, NULL, true,
|
size2index(sizeof(prof_tdata_t)), false, NULL, true,
|
||||||
arena_get(TSDN_NULL, 0, true), true);
|
arena_get(TSDN_NULL, 0, true), true);
|
||||||
if (tdata == NULL)
|
if (tdata == NULL)
|
||||||
@@ -1813,9 +1812,9 @@ prof_tdata_init_impl(tsdn_t *tsdn, uint64_t thr_uid, uint64_t thr_discrim,
|
|||||||
tdata->expired = false;
|
tdata->expired = false;
|
||||||
tdata->tctx_uid_next = 0;
|
tdata->tctx_uid_next = 0;
|
||||||
|
|
||||||
if (ckh_new(tsdn, &tdata->bt2tctx, PROF_CKH_MINITEMS,
|
if (ckh_new(tsd, &tdata->bt2tctx, PROF_CKH_MINITEMS, prof_bt_hash,
|
||||||
prof_bt_hash, prof_bt_keycomp)) {
|
prof_bt_keycomp)) {
|
||||||
idalloctm(tsdn, tdata, NULL, true, true);
|
idalloctm(tsd_tsdn(tsd), tdata, NULL, true, true);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1829,19 +1828,19 @@ prof_tdata_init_impl(tsdn_t *tsdn, uint64_t thr_uid, uint64_t thr_discrim,
|
|||||||
tdata->dumping = false;
|
tdata->dumping = false;
|
||||||
tdata->active = active;
|
tdata->active = active;
|
||||||
|
|
||||||
malloc_mutex_lock(tsdn, &tdatas_mtx);
|
malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx);
|
||||||
tdata_tree_insert(&tdatas, tdata);
|
tdata_tree_insert(&tdatas, tdata);
|
||||||
malloc_mutex_unlock(tsdn, &tdatas_mtx);
|
malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx);
|
||||||
|
|
||||||
return (tdata);
|
return (tdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
prof_tdata_t *
|
prof_tdata_t *
|
||||||
prof_tdata_init(tsdn_t *tsdn)
|
prof_tdata_init(tsd_t *tsd)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (prof_tdata_init_impl(tsdn, prof_thr_uid_alloc(tsdn), 0, NULL,
|
return (prof_tdata_init_impl(tsd, prof_thr_uid_alloc(tsd_tsdn(tsd)), 0,
|
||||||
prof_thread_active_init_get(tsdn)));
|
NULL, prof_thread_active_init_get(tsd_tsdn(tsd))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -1866,31 +1865,29 @@ prof_tdata_should_destroy(tsdn_t *tsdn, prof_tdata_t *tdata,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prof_tdata_destroy_locked(tsdn_t *tsdn, prof_tdata_t *tdata,
|
prof_tdata_destroy_locked(tsd_t *tsd, prof_tdata_t *tdata,
|
||||||
bool even_if_attached)
|
bool even_if_attached)
|
||||||
{
|
{
|
||||||
|
|
||||||
malloc_mutex_assert_owner(tsdn, &tdatas_mtx);
|
malloc_mutex_assert_owner(tsd_tsdn(tsd), &tdatas_mtx);
|
||||||
|
|
||||||
assert(tsdn_null(tsdn) || tsd_prof_tdata_get(tsdn_tsd(tsdn)) != tdata);
|
|
||||||
|
|
||||||
tdata_tree_remove(&tdatas, tdata);
|
tdata_tree_remove(&tdatas, tdata);
|
||||||
|
|
||||||
assert(prof_tdata_should_destroy_unlocked(tdata, even_if_attached));
|
assert(prof_tdata_should_destroy_unlocked(tdata, even_if_attached));
|
||||||
|
|
||||||
if (tdata->thread_name != NULL)
|
if (tdata->thread_name != NULL)
|
||||||
idalloctm(tsdn, tdata->thread_name, NULL, true, true);
|
idalloctm(tsd_tsdn(tsd), tdata->thread_name, NULL, true, true);
|
||||||
ckh_delete(tsdn, &tdata->bt2tctx);
|
ckh_delete(tsd, &tdata->bt2tctx);
|
||||||
idalloctm(tsdn, tdata, NULL, true, true);
|
idalloctm(tsd_tsdn(tsd), tdata, NULL, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prof_tdata_destroy(tsdn_t *tsdn, prof_tdata_t *tdata, bool even_if_attached)
|
prof_tdata_destroy(tsd_t *tsd, prof_tdata_t *tdata, bool even_if_attached)
|
||||||
{
|
{
|
||||||
|
|
||||||
malloc_mutex_lock(tsdn, &tdatas_mtx);
|
malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx);
|
||||||
prof_tdata_destroy_locked(tsdn, tdata, even_if_attached);
|
prof_tdata_destroy_locked(tsd, tdata, even_if_attached);
|
||||||
malloc_mutex_unlock(tsdn, &tdatas_mtx);
|
malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1913,7 +1910,7 @@ prof_tdata_detach(tsd_t *tsd, prof_tdata_t *tdata)
|
|||||||
destroy_tdata = false;
|
destroy_tdata = false;
|
||||||
malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);
|
malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);
|
||||||
if (destroy_tdata)
|
if (destroy_tdata)
|
||||||
prof_tdata_destroy(tsd_tsdn(tsd), tdata, true);
|
prof_tdata_destroy(tsd, tdata, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
prof_tdata_t *
|
prof_tdata_t *
|
||||||
@@ -1926,8 +1923,8 @@ prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata)
|
|||||||
bool active = tdata->active;
|
bool active = tdata->active;
|
||||||
|
|
||||||
prof_tdata_detach(tsd, tdata);
|
prof_tdata_detach(tsd, tdata);
|
||||||
return (prof_tdata_init_impl(tsd_tsdn(tsd), thr_uid, thr_discrim,
|
return (prof_tdata_init_impl(tsd, thr_uid, thr_discrim, thread_name,
|
||||||
thread_name, active));
|
active));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -1956,30 +1953,30 @@ prof_tdata_reset_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
prof_reset(tsdn_t *tsdn, size_t lg_sample)
|
prof_reset(tsd_t *tsd, size_t lg_sample)
|
||||||
{
|
{
|
||||||
prof_tdata_t *next;
|
prof_tdata_t *next;
|
||||||
|
|
||||||
assert(lg_sample < (sizeof(uint64_t) << 3));
|
assert(lg_sample < (sizeof(uint64_t) << 3));
|
||||||
|
|
||||||
malloc_mutex_lock(tsdn, &prof_dump_mtx);
|
malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_mtx);
|
||||||
malloc_mutex_lock(tsdn, &tdatas_mtx);
|
malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx);
|
||||||
|
|
||||||
lg_prof_sample = lg_sample;
|
lg_prof_sample = lg_sample;
|
||||||
|
|
||||||
next = NULL;
|
next = NULL;
|
||||||
do {
|
do {
|
||||||
prof_tdata_t *to_destroy = tdata_tree_iter(&tdatas, next,
|
prof_tdata_t *to_destroy = tdata_tree_iter(&tdatas, next,
|
||||||
prof_tdata_reset_iter, (void *)tsdn);
|
prof_tdata_reset_iter, (void *)tsd);
|
||||||
if (to_destroy != NULL) {
|
if (to_destroy != NULL) {
|
||||||
next = tdata_tree_next(&tdatas, to_destroy);
|
next = tdata_tree_next(&tdatas, to_destroy);
|
||||||
prof_tdata_destroy_locked(tsdn, to_destroy, false);
|
prof_tdata_destroy_locked(tsd, to_destroy, false);
|
||||||
} else
|
} else
|
||||||
next = NULL;
|
next = NULL;
|
||||||
} while (next != NULL);
|
} while (next != NULL);
|
||||||
|
|
||||||
malloc_mutex_unlock(tsdn, &tdatas_mtx);
|
malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx);
|
||||||
malloc_mutex_unlock(tsdn, &prof_dump_mtx);
|
malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2189,7 +2186,7 @@ prof_boot1(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
prof_boot2(tsdn_t *tsdn)
|
prof_boot2(tsd_t *tsd)
|
||||||
{
|
{
|
||||||
|
|
||||||
cassert(config_prof);
|
cassert(config_prof);
|
||||||
@@ -2215,7 +2212,7 @@ prof_boot2(tsdn_t *tsdn)
|
|||||||
WITNESS_RANK_PROF_THREAD_ACTIVE_INIT))
|
WITNESS_RANK_PROF_THREAD_ACTIVE_INIT))
|
||||||
return (true);
|
return (true);
|
||||||
|
|
||||||
if (ckh_new(tsdn, &bt2gctx, PROF_CKH_MINITEMS, prof_bt_hash,
|
if (ckh_new(tsd, &bt2gctx, PROF_CKH_MINITEMS, prof_bt_hash,
|
||||||
prof_bt_keycomp))
|
prof_bt_keycomp))
|
||||||
return (true);
|
return (true);
|
||||||
if (malloc_mutex_init(&bt2gctx_mtx, "prof_bt2gctx",
|
if (malloc_mutex_init(&bt2gctx_mtx, "prof_bt2gctx",
|
||||||
@@ -2246,8 +2243,8 @@ prof_boot2(tsdn_t *tsdn)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
gctx_locks = (malloc_mutex_t *)base_alloc(tsdn, PROF_NCTX_LOCKS
|
gctx_locks = (malloc_mutex_t *)base_alloc(tsd_tsdn(tsd),
|
||||||
* sizeof(malloc_mutex_t));
|
PROF_NCTX_LOCKS * sizeof(malloc_mutex_t));
|
||||||
if (gctx_locks == NULL)
|
if (gctx_locks == NULL)
|
||||||
return (true);
|
return (true);
|
||||||
for (i = 0; i < PROF_NCTX_LOCKS; i++) {
|
for (i = 0; i < PROF_NCTX_LOCKS; i++) {
|
||||||
@@ -2256,7 +2253,7 @@ prof_boot2(tsdn_t *tsdn)
|
|||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
tdata_locks = (malloc_mutex_t *)base_alloc(tsdn,
|
tdata_locks = (malloc_mutex_t *)base_alloc(tsd_tsdn(tsd),
|
||||||
PROF_NTDATA_LOCKS * sizeof(malloc_mutex_t));
|
PROF_NTDATA_LOCKS * sizeof(malloc_mutex_t));
|
||||||
if (tdata_locks == NULL)
|
if (tdata_locks == NULL)
|
||||||
return (true);
|
return (true);
|
||||||
|
|||||||
@@ -96,12 +96,15 @@ rtree_node_init(rtree_t *rtree, unsigned level, rtree_node_elm_t **elmp)
|
|||||||
rtree_node_elm_t *node;
|
rtree_node_elm_t *node;
|
||||||
|
|
||||||
if (atomic_cas_p((void **)elmp, NULL, RTREE_NODE_INITIALIZING)) {
|
if (atomic_cas_p((void **)elmp, NULL, RTREE_NODE_INITIALIZING)) {
|
||||||
|
spin_t spinner;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Another thread is already in the process of initializing.
|
* Another thread is already in the process of initializing.
|
||||||
* Spin-wait until initialization is complete.
|
* Spin-wait until initialization is complete.
|
||||||
*/
|
*/
|
||||||
|
spin_init(&spinner);
|
||||||
do {
|
do {
|
||||||
CPU_SPINWAIT;
|
spin_adaptive(&spinner);
|
||||||
node = atomic_read_p((void **)elmp);
|
node = atomic_read_p((void **)elmp);
|
||||||
} while (node == RTREE_NODE_INITIALIZING);
|
} while (node == RTREE_NODE_INITIALIZING);
|
||||||
} else {
|
} else {
|
||||||
@@ -125,5 +128,5 @@ rtree_node_elm_t *
|
|||||||
rtree_child_read_hard(rtree_t *rtree, rtree_node_elm_t *elm, unsigned level)
|
rtree_child_read_hard(rtree_t *rtree, rtree_node_elm_t *elm, unsigned level)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (rtree_node_init(rtree, level, &elm->child));
|
return (rtree_node_init(rtree, level+1, &elm->child));
|
||||||
}
|
}
|
||||||
|
|||||||
2
src/spin.c
Normal file
2
src/spin.c
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define JEMALLOC_SPIN_C_
|
||||||
|
#include "jemalloc/internal/jemalloc_internal.h"
|
||||||
1276
src/stats.c
Normal file → Executable file
1276
src/stats.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
14
src/tcache.c
Normal file → Executable file
14
src/tcache.c
Normal file → Executable file
@@ -445,14 +445,14 @@ tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tcaches_create(tsdn_t *tsdn, unsigned *r_ind)
|
tcaches_create(tsd_t *tsd, unsigned *r_ind)
|
||||||
{
|
{
|
||||||
arena_t *arena;
|
arena_t *arena;
|
||||||
tcache_t *tcache;
|
tcache_t *tcache;
|
||||||
tcaches_t *elm;
|
tcaches_t *elm;
|
||||||
|
|
||||||
if (tcaches == NULL) {
|
if (tcaches == NULL) {
|
||||||
tcaches = base_alloc(tsdn, sizeof(tcache_t *) *
|
tcaches = base_alloc(tsd_tsdn(tsd), sizeof(tcache_t *) *
|
||||||
(MALLOCX_TCACHE_MAX+1));
|
(MALLOCX_TCACHE_MAX+1));
|
||||||
if (tcaches == NULL)
|
if (tcaches == NULL)
|
||||||
return (true);
|
return (true);
|
||||||
@@ -460,10 +460,10 @@ tcaches_create(tsdn_t *tsdn, unsigned *r_ind)
|
|||||||
|
|
||||||
if (tcaches_avail == NULL && tcaches_past > MALLOCX_TCACHE_MAX)
|
if (tcaches_avail == NULL && tcaches_past > MALLOCX_TCACHE_MAX)
|
||||||
return (true);
|
return (true);
|
||||||
arena = arena_ichoose(tsdn, NULL);
|
arena = arena_ichoose(tsd, NULL);
|
||||||
if (unlikely(arena == NULL))
|
if (unlikely(arena == NULL))
|
||||||
return (true);
|
return (true);
|
||||||
tcache = tcache_create(tsdn, arena);
|
tcache = tcache_create(tsd_tsdn(tsd), arena);
|
||||||
if (tcache == NULL)
|
if (tcache == NULL)
|
||||||
return (true);
|
return (true);
|
||||||
|
|
||||||
@@ -517,12 +517,12 @@ tcache_boot(tsdn_t *tsdn)
|
|||||||
* If necessary, clamp opt_lg_tcache_max, now that large_maxclass is
|
* If necessary, clamp opt_lg_tcache_max, now that large_maxclass is
|
||||||
* known.
|
* known.
|
||||||
*/
|
*/
|
||||||
if (opt_lg_tcache_max < 0 || (1U << opt_lg_tcache_max) < SMALL_MAXCLASS)
|
if (opt_lg_tcache_max < 0 || (ZU(1) << opt_lg_tcache_max) < SMALL_MAXCLASS)
|
||||||
tcache_maxclass = SMALL_MAXCLASS;
|
tcache_maxclass = SMALL_MAXCLASS;
|
||||||
else if ((1U << opt_lg_tcache_max) > large_maxclass)
|
else if ((ZU(1) << opt_lg_tcache_max) > large_maxclass)
|
||||||
tcache_maxclass = large_maxclass;
|
tcache_maxclass = large_maxclass;
|
||||||
else
|
else
|
||||||
tcache_maxclass = (1U << opt_lg_tcache_max);
|
tcache_maxclass = (ZU(1) << opt_lg_tcache_max);
|
||||||
|
|
||||||
nhbins = size2index(tcache_maxclass) + 1;
|
nhbins = size2index(tcache_maxclass) + 1;
|
||||||
|
|
||||||
|
|||||||
10
src/tsd.c
10
src/tsd.c
@@ -171,10 +171,10 @@ tsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block)
|
|||||||
tsd_init_block_t *iter;
|
tsd_init_block_t *iter;
|
||||||
|
|
||||||
/* Check whether this thread has already inserted into the list. */
|
/* Check whether this thread has already inserted into the list. */
|
||||||
malloc_mutex_lock(NULL, &head->lock);
|
malloc_mutex_lock(TSDN_NULL, &head->lock);
|
||||||
ql_foreach(iter, &head->blocks, link) {
|
ql_foreach(iter, &head->blocks, link) {
|
||||||
if (iter->thread == self) {
|
if (iter->thread == self) {
|
||||||
malloc_mutex_unlock(NULL, &head->lock);
|
malloc_mutex_unlock(TSDN_NULL, &head->lock);
|
||||||
return (iter->data);
|
return (iter->data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ tsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block)
|
|||||||
ql_elm_new(block, link);
|
ql_elm_new(block, link);
|
||||||
block->thread = self;
|
block->thread = self;
|
||||||
ql_tail_insert(&head->blocks, block, link);
|
ql_tail_insert(&head->blocks, block, link);
|
||||||
malloc_mutex_unlock(NULL, &head->lock);
|
malloc_mutex_unlock(TSDN_NULL, &head->lock);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,8 +190,8 @@ void
|
|||||||
tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block)
|
tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block)
|
||||||
{
|
{
|
||||||
|
|
||||||
malloc_mutex_lock(NULL, &head->lock);
|
malloc_mutex_lock(TSDN_NULL, &head->lock);
|
||||||
ql_remove(&head->blocks, block, link);
|
ql_remove(&head->blocks, block, link);
|
||||||
malloc_mutex_unlock(NULL, &head->lock);
|
malloc_mutex_unlock(TSDN_NULL, &head->lock);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
4
src/util.c
Normal file → Executable file
4
src/util.c
Normal file → Executable file
@@ -49,7 +49,7 @@ static void
|
|||||||
wrtmessage(void *cbopaque, const char *s)
|
wrtmessage(void *cbopaque, const char *s)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef SYS_write
|
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_write)
|
||||||
/*
|
/*
|
||||||
* Use syscall(2) rather than write(2) when possible in order to avoid
|
* Use syscall(2) rather than write(2) when possible in order to avoid
|
||||||
* the possibility of memory allocation within libc. This is necessary
|
* the possibility of memory allocation within libc. This is necessary
|
||||||
@@ -200,7 +200,7 @@ malloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base)
|
|||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
if (neg)
|
if (neg)
|
||||||
ret = -ret;
|
ret = (uintmax_t)(-((intmax_t)ret));
|
||||||
|
|
||||||
if (p == ns) {
|
if (p == ns) {
|
||||||
/* No conversion performed. */
|
/* No conversion performed. */
|
||||||
|
|||||||
186
src/zone.c
186
src/zone.c
@@ -4,7 +4,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The malloc_default_purgeable_zone function is only available on >= 10.6.
|
* The malloc_default_purgeable_zone() function is only available on >= 10.6.
|
||||||
* We need to check whether it is present at runtime, thus the weak_import.
|
* We need to check whether it is present at runtime, thus the weak_import.
|
||||||
*/
|
*/
|
||||||
extern malloc_zone_t *malloc_default_purgeable_zone(void)
|
extern malloc_zone_t *malloc_default_purgeable_zone(void)
|
||||||
@@ -13,8 +13,9 @@ JEMALLOC_ATTR(weak_import);
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Data. */
|
/* Data. */
|
||||||
|
|
||||||
static malloc_zone_t zone;
|
static malloc_zone_t *default_zone, *purgeable_zone;
|
||||||
static struct malloc_introspection_t zone_introspect;
|
static malloc_zone_t jemalloc_zone;
|
||||||
|
static struct malloc_introspection_t jemalloc_zone_introspect;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Function prototypes for non-inline static functions. */
|
/* Function prototypes for non-inline static functions. */
|
||||||
@@ -164,89 +165,103 @@ static void
|
|||||||
zone_force_unlock(malloc_zone_t *zone)
|
zone_force_unlock(malloc_zone_t *zone)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call jemalloc_postfork_child() rather than
|
||||||
|
* jemalloc_postfork_parent(), because this function is executed by both
|
||||||
|
* parent and child. The parent can tolerate having state
|
||||||
|
* reinitialized, but the child cannot unlock mutexes that were locked
|
||||||
|
* by the parent.
|
||||||
|
*/
|
||||||
if (isthreaded)
|
if (isthreaded)
|
||||||
jemalloc_postfork_parent();
|
jemalloc_postfork_child();
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ATTR(constructor)
|
static void
|
||||||
void
|
zone_init(void)
|
||||||
register_zone(void)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
jemalloc_zone.size = (void *)zone_size;
|
||||||
* If something else replaced the system default zone allocator, don't
|
jemalloc_zone.malloc = (void *)zone_malloc;
|
||||||
* register jemalloc's.
|
jemalloc_zone.calloc = (void *)zone_calloc;
|
||||||
*/
|
jemalloc_zone.valloc = (void *)zone_valloc;
|
||||||
malloc_zone_t *default_zone = malloc_default_zone();
|
jemalloc_zone.free = (void *)zone_free;
|
||||||
malloc_zone_t *purgeable_zone = NULL;
|
jemalloc_zone.realloc = (void *)zone_realloc;
|
||||||
if (!default_zone->zone_name ||
|
jemalloc_zone.destroy = (void *)zone_destroy;
|
||||||
strcmp(default_zone->zone_name, "DefaultMallocZone") != 0) {
|
jemalloc_zone.zone_name = "jemalloc_zone";
|
||||||
return;
|
jemalloc_zone.batch_malloc = NULL;
|
||||||
}
|
jemalloc_zone.batch_free = NULL;
|
||||||
|
jemalloc_zone.introspect = &jemalloc_zone_introspect;
|
||||||
zone.size = (void *)zone_size;
|
jemalloc_zone.version = JEMALLOC_ZONE_VERSION;
|
||||||
zone.malloc = (void *)zone_malloc;
|
|
||||||
zone.calloc = (void *)zone_calloc;
|
|
||||||
zone.valloc = (void *)zone_valloc;
|
|
||||||
zone.free = (void *)zone_free;
|
|
||||||
zone.realloc = (void *)zone_realloc;
|
|
||||||
zone.destroy = (void *)zone_destroy;
|
|
||||||
zone.zone_name = "jemalloc_zone";
|
|
||||||
zone.batch_malloc = NULL;
|
|
||||||
zone.batch_free = NULL;
|
|
||||||
zone.introspect = &zone_introspect;
|
|
||||||
zone.version = JEMALLOC_ZONE_VERSION;
|
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 5)
|
#if (JEMALLOC_ZONE_VERSION >= 5)
|
||||||
zone.memalign = zone_memalign;
|
jemalloc_zone.memalign = zone_memalign;
|
||||||
#endif
|
#endif
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 6)
|
#if (JEMALLOC_ZONE_VERSION >= 6)
|
||||||
zone.free_definite_size = zone_free_definite_size;
|
jemalloc_zone.free_definite_size = zone_free_definite_size;
|
||||||
#endif
|
#endif
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 8)
|
#if (JEMALLOC_ZONE_VERSION >= 8)
|
||||||
zone.pressure_relief = NULL;
|
jemalloc_zone.pressure_relief = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
zone_introspect.enumerator = NULL;
|
jemalloc_zone_introspect.enumerator = NULL;
|
||||||
zone_introspect.good_size = (void *)zone_good_size;
|
jemalloc_zone_introspect.good_size = (void *)zone_good_size;
|
||||||
zone_introspect.check = NULL;
|
jemalloc_zone_introspect.check = NULL;
|
||||||
zone_introspect.print = NULL;
|
jemalloc_zone_introspect.print = NULL;
|
||||||
zone_introspect.log = NULL;
|
jemalloc_zone_introspect.log = NULL;
|
||||||
zone_introspect.force_lock = (void *)zone_force_lock;
|
jemalloc_zone_introspect.force_lock = (void *)zone_force_lock;
|
||||||
zone_introspect.force_unlock = (void *)zone_force_unlock;
|
jemalloc_zone_introspect.force_unlock = (void *)zone_force_unlock;
|
||||||
zone_introspect.statistics = NULL;
|
jemalloc_zone_introspect.statistics = NULL;
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 6)
|
#if (JEMALLOC_ZONE_VERSION >= 6)
|
||||||
zone_introspect.zone_locked = NULL;
|
jemalloc_zone_introspect.zone_locked = NULL;
|
||||||
#endif
|
#endif
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 7)
|
#if (JEMALLOC_ZONE_VERSION >= 7)
|
||||||
zone_introspect.enable_discharge_checking = NULL;
|
jemalloc_zone_introspect.enable_discharge_checking = NULL;
|
||||||
zone_introspect.disable_discharge_checking = NULL;
|
jemalloc_zone_introspect.disable_discharge_checking = NULL;
|
||||||
zone_introspect.discharge = NULL;
|
jemalloc_zone_introspect.discharge = NULL;
|
||||||
#ifdef __BLOCKS__
|
# ifdef __BLOCKS__
|
||||||
zone_introspect.enumerate_discharged_pointers = NULL;
|
jemalloc_zone_introspect.enumerate_discharged_pointers = NULL;
|
||||||
#else
|
# else
|
||||||
zone_introspect.enumerate_unavailable_without_blocks = NULL;
|
jemalloc_zone_introspect.enumerate_unavailable_without_blocks = NULL;
|
||||||
#endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static malloc_zone_t *
|
||||||
|
zone_default_get(void)
|
||||||
|
{
|
||||||
|
malloc_zone_t **zones = NULL;
|
||||||
|
unsigned int num_zones = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The default purgeable zone is created lazily by OSX's libc. It uses
|
* On OSX 10.12, malloc_default_zone returns a special zone that is not
|
||||||
* the default zone when it is created for "small" allocations
|
* present in the list of registered zones. That zone uses a "lite zone"
|
||||||
* (< 15 KiB), but assumes the default zone is a scalable_zone. This
|
* if one is present (apparently enabled when malloc stack logging is
|
||||||
* obviously fails when the default zone is the jemalloc zone, so
|
* enabled), or the first registered zone otherwise. In practice this
|
||||||
* malloc_default_purgeable_zone is called beforehand so that the
|
* means unless malloc stack logging is enabled, the first registered
|
||||||
* default purgeable zone is created when the default zone is still
|
* zone is the default. So get the list of zones to get the first one,
|
||||||
* a scalable_zone. As purgeable zones only exist on >= 10.6, we need
|
* instead of relying on malloc_default_zone.
|
||||||
* to check for the existence of malloc_default_purgeable_zone() at
|
|
||||||
* run time.
|
|
||||||
*/
|
*/
|
||||||
if (malloc_default_purgeable_zone != NULL)
|
if (KERN_SUCCESS != malloc_get_all_zones(0, NULL,
|
||||||
purgeable_zone = malloc_default_purgeable_zone();
|
(vm_address_t**)&zones, &num_zones)) {
|
||||||
|
/*
|
||||||
|
* Reset the value in case the failure happened after it was
|
||||||
|
* set.
|
||||||
|
*/
|
||||||
|
num_zones = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Register the custom zone. At this point it won't be the default. */
|
if (num_zones)
|
||||||
malloc_zone_register(&zone);
|
return (zones[0]);
|
||||||
|
|
||||||
|
return (malloc_default_zone());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* As written, this function can only promote jemalloc_zone. */
|
||||||
|
static void
|
||||||
|
zone_promote(void)
|
||||||
|
{
|
||||||
|
malloc_zone_t *zone;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
default_zone = malloc_default_zone();
|
|
||||||
/*
|
/*
|
||||||
* Unregister and reregister the default zone. On OSX >= 10.6,
|
* Unregister and reregister the default zone. On OSX >= 10.6,
|
||||||
* unregistering takes the last registered zone and places it
|
* unregistering takes the last registered zone and places it
|
||||||
@@ -257,6 +272,7 @@ register_zone(void)
|
|||||||
*/
|
*/
|
||||||
malloc_zone_unregister(default_zone);
|
malloc_zone_unregister(default_zone);
|
||||||
malloc_zone_register(default_zone);
|
malloc_zone_register(default_zone);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On OSX 10.6, having the default purgeable zone appear before
|
* On OSX 10.6, having the default purgeable zone appear before
|
||||||
* the default zone makes some things crash because it thinks it
|
* the default zone makes some things crash because it thinks it
|
||||||
@@ -268,9 +284,47 @@ register_zone(void)
|
|||||||
* above, i.e. the default zone. Registering it again then puts
|
* above, i.e. the default zone. Registering it again then puts
|
||||||
* it at the end, obviously after the default zone.
|
* it at the end, obviously after the default zone.
|
||||||
*/
|
*/
|
||||||
if (purgeable_zone) {
|
if (purgeable_zone != NULL) {
|
||||||
malloc_zone_unregister(purgeable_zone);
|
malloc_zone_unregister(purgeable_zone);
|
||||||
malloc_zone_register(purgeable_zone);
|
malloc_zone_register(purgeable_zone);
|
||||||
}
|
}
|
||||||
} while (malloc_default_zone() != &zone);
|
|
||||||
|
zone = zone_default_get();
|
||||||
|
} while (zone != &jemalloc_zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_ATTR(constructor)
|
||||||
|
void
|
||||||
|
zone_register(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If something else replaced the system default zone allocator, don't
|
||||||
|
* register jemalloc's.
|
||||||
|
*/
|
||||||
|
default_zone = zone_default_get();
|
||||||
|
if (!default_zone->zone_name || strcmp(default_zone->zone_name,
|
||||||
|
"DefaultMallocZone") != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The default purgeable zone is created lazily by OSX's libc. It uses
|
||||||
|
* the default zone when it is created for "small" allocations
|
||||||
|
* (< 15 KiB), but assumes the default zone is a scalable_zone. This
|
||||||
|
* obviously fails when the default zone is the jemalloc zone, so
|
||||||
|
* malloc_default_purgeable_zone() is called beforehand so that the
|
||||||
|
* default purgeable zone is created when the default zone is still
|
||||||
|
* a scalable_zone. As purgeable zones only exist on >= 10.6, we need
|
||||||
|
* to check for the existence of malloc_default_purgeable_zone() at
|
||||||
|
* run time.
|
||||||
|
*/
|
||||||
|
purgeable_zone = (malloc_default_purgeable_zone == NULL) ? NULL :
|
||||||
|
malloc_default_purgeable_zone();
|
||||||
|
|
||||||
|
/* Register the custom zone. At this point it won't be the default. */
|
||||||
|
zone_init();
|
||||||
|
malloc_zone_register(&jemalloc_zone);
|
||||||
|
|
||||||
|
/* Promote the custom zone to be default. */
|
||||||
|
zone_promote();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
CRITICAL_SECTION lock;
|
CRITICAL_SECTION lock;
|
||||||
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
||||||
|
os_unfair_lock lock;
|
||||||
#elif (defined(JEMALLOC_OSSPIN))
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
OSSpinLock lock;
|
OSSpinLock lock;
|
||||||
#else
|
#else
|
||||||
|
|||||||
4
test/integration/MALLOCX_ARENA.c
Normal file → Executable file
4
test/integration/MALLOCX_ARENA.c
Normal file → Executable file
@@ -19,8 +19,8 @@ thd_start(void *arg)
|
|||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
sz = sizeof(arena_ind);
|
sz = sizeof(arena_ind);
|
||||||
assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.extend", (void *)&arena_ind, &sz, NULL, 0),
|
||||||
"Error in arenas.extend");
|
0, "Error in arenas.extend");
|
||||||
|
|
||||||
if (thread_ind % 4 != 3) {
|
if (thread_ind % 4 != 3) {
|
||||||
size_t mib[3];
|
size_t mib[3];
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
#include "test/jemalloc_test.h"
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
#define CHUNK 0x400000
|
#define CHUNK 0x400000
|
||||||
/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */
|
#define MAXALIGN (((size_t)1) << 23)
|
||||||
#define MAXALIGN ((size_t)0x2000000LU)
|
|
||||||
#define NITER 4
|
/*
|
||||||
|
* On systems which can't merge extents, tests that call this function generate
|
||||||
|
* a lot of dirty memory very quickly. Purging between cycles mitigates
|
||||||
|
* potential OOM on e.g. 32-bit Windows.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
purge(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
||||||
|
"Unexpected mallctl error");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_BEGIN(test_alignment_errors)
|
TEST_BEGIN(test_alignment_errors)
|
||||||
{
|
{
|
||||||
@@ -74,6 +85,7 @@ TEST_END
|
|||||||
|
|
||||||
TEST_BEGIN(test_alignment_and_size)
|
TEST_BEGIN(test_alignment_and_size)
|
||||||
{
|
{
|
||||||
|
#define NITER 4
|
||||||
size_t alignment, size, total;
|
size_t alignment, size, total;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
void *ps[NITER];
|
void *ps[NITER];
|
||||||
@@ -110,7 +122,9 @@ TEST_BEGIN(test_alignment_and_size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
purge();
|
||||||
}
|
}
|
||||||
|
#undef NITER
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
|
|||||||
17
test/integration/allocated.c
Normal file → Executable file
17
test/integration/allocated.c
Normal file → Executable file
@@ -18,14 +18,14 @@ thd_start(void *arg)
|
|||||||
size_t sz, usize;
|
size_t sz, usize;
|
||||||
|
|
||||||
sz = sizeof(a0);
|
sz = sizeof(a0);
|
||||||
if ((err = mallctl("thread.allocated", &a0, &sz, NULL, 0))) {
|
if ((err = mallctl("thread.allocated", (void *)&a0, &sz, NULL, 0))) {
|
||||||
if (err == ENOENT)
|
if (err == ENOENT)
|
||||||
goto label_ENOENT;
|
goto label_ENOENT;
|
||||||
test_fail("%s(): Error in mallctl(): %s", __func__,
|
test_fail("%s(): Error in mallctl(): %s", __func__,
|
||||||
strerror(err));
|
strerror(err));
|
||||||
}
|
}
|
||||||
sz = sizeof(ap0);
|
sz = sizeof(ap0);
|
||||||
if ((err = mallctl("thread.allocatedp", &ap0, &sz, NULL, 0))) {
|
if ((err = mallctl("thread.allocatedp", (void *)&ap0, &sz, NULL, 0))) {
|
||||||
if (err == ENOENT)
|
if (err == ENOENT)
|
||||||
goto label_ENOENT;
|
goto label_ENOENT;
|
||||||
test_fail("%s(): Error in mallctl(): %s", __func__,
|
test_fail("%s(): Error in mallctl(): %s", __func__,
|
||||||
@@ -36,14 +36,15 @@ thd_start(void *arg)
|
|||||||
"storage");
|
"storage");
|
||||||
|
|
||||||
sz = sizeof(d0);
|
sz = sizeof(d0);
|
||||||
if ((err = mallctl("thread.deallocated", &d0, &sz, NULL, 0))) {
|
if ((err = mallctl("thread.deallocated", (void *)&d0, &sz, NULL, 0))) {
|
||||||
if (err == ENOENT)
|
if (err == ENOENT)
|
||||||
goto label_ENOENT;
|
goto label_ENOENT;
|
||||||
test_fail("%s(): Error in mallctl(): %s", __func__,
|
test_fail("%s(): Error in mallctl(): %s", __func__,
|
||||||
strerror(err));
|
strerror(err));
|
||||||
}
|
}
|
||||||
sz = sizeof(dp0);
|
sz = sizeof(dp0);
|
||||||
if ((err = mallctl("thread.deallocatedp", &dp0, &sz, NULL, 0))) {
|
if ((err = mallctl("thread.deallocatedp", (void *)&dp0, &sz, NULL,
|
||||||
|
0))) {
|
||||||
if (err == ENOENT)
|
if (err == ENOENT)
|
||||||
goto label_ENOENT;
|
goto label_ENOENT;
|
||||||
test_fail("%s(): Error in mallctl(): %s", __func__,
|
test_fail("%s(): Error in mallctl(): %s", __func__,
|
||||||
@@ -57,9 +58,9 @@ thd_start(void *arg)
|
|||||||
assert_ptr_not_null(p, "Unexpected malloc() error");
|
assert_ptr_not_null(p, "Unexpected malloc() error");
|
||||||
|
|
||||||
sz = sizeof(a1);
|
sz = sizeof(a1);
|
||||||
mallctl("thread.allocated", &a1, &sz, NULL, 0);
|
mallctl("thread.allocated", (void *)&a1, &sz, NULL, 0);
|
||||||
sz = sizeof(ap1);
|
sz = sizeof(ap1);
|
||||||
mallctl("thread.allocatedp", &ap1, &sz, NULL, 0);
|
mallctl("thread.allocatedp", (void *)&ap1, &sz, NULL, 0);
|
||||||
assert_u64_eq(*ap1, a1,
|
assert_u64_eq(*ap1, a1,
|
||||||
"Dereferenced \"thread.allocatedp\" value should equal "
|
"Dereferenced \"thread.allocatedp\" value should equal "
|
||||||
"\"thread.allocated\" value");
|
"\"thread.allocated\" value");
|
||||||
@@ -74,9 +75,9 @@ thd_start(void *arg)
|
|||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
sz = sizeof(d1);
|
sz = sizeof(d1);
|
||||||
mallctl("thread.deallocated", &d1, &sz, NULL, 0);
|
mallctl("thread.deallocated", (void *)&d1, &sz, NULL, 0);
|
||||||
sz = sizeof(dp1);
|
sz = sizeof(dp1);
|
||||||
mallctl("thread.deallocatedp", &dp1, &sz, NULL, 0);
|
mallctl("thread.deallocatedp", (void *)&dp1, &sz, NULL, 0);
|
||||||
assert_u64_eq(*dp1, d1,
|
assert_u64_eq(*dp1, d1,
|
||||||
"Dereferenced \"thread.deallocatedp\" value should equal "
|
"Dereferenced \"thread.deallocatedp\" value should equal "
|
||||||
"\"thread.deallocated\" value");
|
"\"thread.deallocated\" value");
|
||||||
|
|||||||
@@ -137,8 +137,8 @@ TEST_BEGIN(test_chunk)
|
|||||||
bool xallocx_success_a, xallocx_success_b, xallocx_success_c;
|
bool xallocx_success_a, xallocx_success_b, xallocx_success_c;
|
||||||
|
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.extend", (void *)&arena_ind, &sz, NULL, 0),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;
|
flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;
|
||||||
|
|
||||||
/* Install custom chunk hooks. */
|
/* Install custom chunk hooks. */
|
||||||
@@ -148,8 +148,9 @@ TEST_BEGIN(test_chunk)
|
|||||||
hooks_mib[1] = (size_t)arena_ind;
|
hooks_mib[1] = (size_t)arena_ind;
|
||||||
old_size = sizeof(chunk_hooks_t);
|
old_size = sizeof(chunk_hooks_t);
|
||||||
new_size = sizeof(chunk_hooks_t);
|
new_size = sizeof(chunk_hooks_t);
|
||||||
assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, &old_hooks, &old_size,
|
assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, (void *)&old_hooks,
|
||||||
&new_hooks, new_size), 0, "Unexpected chunk_hooks error");
|
&old_size, (void *)&new_hooks, new_size), 0,
|
||||||
|
"Unexpected chunk_hooks error");
|
||||||
orig_hooks = old_hooks;
|
orig_hooks = old_hooks;
|
||||||
assert_ptr_ne(old_hooks.alloc, chunk_alloc, "Unexpected alloc error");
|
assert_ptr_ne(old_hooks.alloc, chunk_alloc, "Unexpected alloc error");
|
||||||
assert_ptr_ne(old_hooks.dalloc, chunk_dalloc,
|
assert_ptr_ne(old_hooks.dalloc, chunk_dalloc,
|
||||||
@@ -164,18 +165,18 @@ TEST_BEGIN(test_chunk)
|
|||||||
|
|
||||||
/* Get large size classes. */
|
/* Get large size classes. */
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("arenas.lrun.0.size", &large0, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.lrun.0.size", (void *)&large0, &sz, NULL,
|
||||||
"Unexpected arenas.lrun.0.size failure");
|
0), 0, "Unexpected arenas.lrun.0.size failure");
|
||||||
assert_d_eq(mallctl("arenas.lrun.1.size", &large1, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.lrun.1.size", (void *)&large1, &sz, NULL,
|
||||||
"Unexpected arenas.lrun.1.size failure");
|
0), 0, "Unexpected arenas.lrun.1.size failure");
|
||||||
|
|
||||||
/* Get huge size classes. */
|
/* Get huge size classes. */
|
||||||
assert_d_eq(mallctl("arenas.hchunk.0.size", &huge0, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.hchunk.0.size", (void *)&huge0, &sz, NULL,
|
||||||
"Unexpected arenas.hchunk.0.size failure");
|
0), 0, "Unexpected arenas.hchunk.0.size failure");
|
||||||
assert_d_eq(mallctl("arenas.hchunk.1.size", &huge1, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.hchunk.1.size", (void *)&huge1, &sz, NULL,
|
||||||
"Unexpected arenas.hchunk.1.size failure");
|
0), 0, "Unexpected arenas.hchunk.1.size failure");
|
||||||
assert_d_eq(mallctl("arenas.hchunk.2.size", &huge2, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.hchunk.2.size", (void *)&huge2, &sz, NULL,
|
||||||
"Unexpected arenas.hchunk.2.size failure");
|
0), 0, "Unexpected arenas.hchunk.2.size failure");
|
||||||
|
|
||||||
/* Test dalloc/decommit/purge cascade. */
|
/* Test dalloc/decommit/purge cascade. */
|
||||||
purge_miblen = sizeof(purge_mib)/sizeof(size_t);
|
purge_miblen = sizeof(purge_mib)/sizeof(size_t);
|
||||||
@@ -265,9 +266,9 @@ TEST_BEGIN(test_chunk)
|
|||||||
|
|
||||||
/* Restore chunk hooks. */
|
/* Restore chunk hooks. */
|
||||||
assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, NULL, NULL,
|
assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, NULL, NULL,
|
||||||
&old_hooks, new_size), 0, "Unexpected chunk_hooks error");
|
(void *)&old_hooks, new_size), 0, "Unexpected chunk_hooks error");
|
||||||
assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, &old_hooks, &old_size,
|
assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, (void *)&old_hooks,
|
||||||
NULL, 0), 0, "Unexpected chunk_hooks error");
|
&old_size, NULL, 0), 0, "Unexpected chunk_hooks error");
|
||||||
assert_ptr_eq(old_hooks.alloc, orig_hooks.alloc,
|
assert_ptr_eq(old_hooks.alloc, orig_hooks.alloc,
|
||||||
"Unexpected alloc error");
|
"Unexpected alloc error");
|
||||||
assert_ptr_eq(old_hooks.dalloc, orig_hooks.dalloc,
|
assert_ptr_eq(old_hooks.dalloc, orig_hooks.dalloc,
|
||||||
|
|||||||
34
test/integration/mallocx.c
Normal file → Executable file
34
test/integration/mallocx.c
Normal file → Executable file
@@ -11,7 +11,7 @@ get_nsizes_impl(const char *cmd)
|
|||||||
size_t z;
|
size_t z;
|
||||||
|
|
||||||
z = sizeof(unsigned);
|
z = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,
|
assert_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0,
|
||||||
"Unexpected mallctl(\"%s\", ...) failure", cmd);
|
"Unexpected mallctl(\"%s\", ...) failure", cmd);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -37,7 +37,7 @@ get_size_impl(const char *cmd, size_t ind)
|
|||||||
0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
|
0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
|
||||||
mib[2] = ind;
|
mib[2] = ind;
|
||||||
z = sizeof(size_t);
|
z = sizeof(size_t);
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0),
|
||||||
0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
|
0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -50,6 +50,19 @@ get_huge_size(size_t ind)
|
|||||||
return (get_size_impl("arenas.hchunk.0.size", ind));
|
return (get_size_impl("arenas.hchunk.0.size", ind));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On systems which can't merge extents, tests that call this function generate
|
||||||
|
* a lot of dirty memory very quickly. Purging between cycles mitigates
|
||||||
|
* potential OOM on e.g. 32-bit Windows.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
purge(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
||||||
|
"Unexpected mallctl error");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_BEGIN(test_overflow)
|
TEST_BEGIN(test_overflow)
|
||||||
{
|
{
|
||||||
size_t hugemax;
|
size_t hugemax;
|
||||||
@@ -96,6 +109,7 @@ TEST_BEGIN(test_oom)
|
|||||||
if (ptrs[i] != NULL)
|
if (ptrs[i] != NULL)
|
||||||
dallocx(ptrs[i], 0);
|
dallocx(ptrs[i], 0);
|
||||||
}
|
}
|
||||||
|
purge();
|
||||||
|
|
||||||
#if LG_SIZEOF_PTR == 3
|
#if LG_SIZEOF_PTR == 3
|
||||||
assert_ptr_null(mallocx(0x8000000000000000ULL,
|
assert_ptr_null(mallocx(0x8000000000000000ULL,
|
||||||
@@ -113,7 +127,7 @@ TEST_END
|
|||||||
|
|
||||||
TEST_BEGIN(test_basic)
|
TEST_BEGIN(test_basic)
|
||||||
{
|
{
|
||||||
#define MAXSZ (((size_t)1) << 26)
|
#define MAXSZ (((size_t)1) << 23)
|
||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
for (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) {
|
for (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) {
|
||||||
@@ -122,23 +136,28 @@ TEST_BEGIN(test_basic)
|
|||||||
nsz = nallocx(sz, 0);
|
nsz = nallocx(sz, 0);
|
||||||
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
|
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
|
||||||
p = mallocx(sz, 0);
|
p = mallocx(sz, 0);
|
||||||
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
assert_ptr_not_null(p,
|
||||||
|
"Unexpected mallocx(size=%zx, flags=0) error", sz);
|
||||||
rsz = sallocx(p, 0);
|
rsz = sallocx(p, 0);
|
||||||
assert_zu_ge(rsz, sz, "Real size smaller than expected");
|
assert_zu_ge(rsz, sz, "Real size smaller than expected");
|
||||||
assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch");
|
assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch");
|
||||||
dallocx(p, 0);
|
dallocx(p, 0);
|
||||||
|
|
||||||
p = mallocx(sz, 0);
|
p = mallocx(sz, 0);
|
||||||
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
assert_ptr_not_null(p,
|
||||||
|
"Unexpected mallocx(size=%zx, flags=0) error", sz);
|
||||||
dallocx(p, 0);
|
dallocx(p, 0);
|
||||||
|
|
||||||
nsz = nallocx(sz, MALLOCX_ZERO);
|
nsz = nallocx(sz, MALLOCX_ZERO);
|
||||||
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
|
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
|
||||||
p = mallocx(sz, MALLOCX_ZERO);
|
p = mallocx(sz, MALLOCX_ZERO);
|
||||||
assert_ptr_not_null(p, "Unexpected mallocx() error");
|
assert_ptr_not_null(p,
|
||||||
|
"Unexpected mallocx(size=%zx, flags=MALLOCX_ZERO) error",
|
||||||
|
nsz);
|
||||||
rsz = sallocx(p, 0);
|
rsz = sallocx(p, 0);
|
||||||
assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch");
|
assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch");
|
||||||
dallocx(p, 0);
|
dallocx(p, 0);
|
||||||
|
purge();
|
||||||
}
|
}
|
||||||
#undef MAXSZ
|
#undef MAXSZ
|
||||||
}
|
}
|
||||||
@@ -146,7 +165,7 @@ TEST_END
|
|||||||
|
|
||||||
TEST_BEGIN(test_alignment_and_size)
|
TEST_BEGIN(test_alignment_and_size)
|
||||||
{
|
{
|
||||||
#define MAXALIGN (((size_t)1) << 25)
|
#define MAXALIGN (((size_t)1) << 23)
|
||||||
#define NITER 4
|
#define NITER 4
|
||||||
size_t nsz, rsz, sz, alignment, total;
|
size_t nsz, rsz, sz, alignment, total;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@@ -196,6 +215,7 @@ TEST_BEGIN(test_alignment_and_size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
purge();
|
||||||
}
|
}
|
||||||
#undef MAXALIGN
|
#undef MAXALIGN
|
||||||
#undef NITER
|
#undef NITER
|
||||||
|
|||||||
8
test/integration/overflow.c
Normal file → Executable file
8
test/integration/overflow.c
Normal file → Executable file
@@ -8,8 +8,8 @@ TEST_BEGIN(test_overflow)
|
|||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("arenas.nhchunks", &nhchunks, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.nhchunks", (void *)&nhchunks, &sz, NULL, 0),
|
||||||
"Unexpected mallctl() error");
|
0, "Unexpected mallctl() error");
|
||||||
|
|
||||||
miblen = sizeof(mib) / sizeof(size_t);
|
miblen = sizeof(mib) / sizeof(size_t);
|
||||||
assert_d_eq(mallctlnametomib("arenas.hchunk.0.size", mib, &miblen), 0,
|
assert_d_eq(mallctlnametomib("arenas.hchunk.0.size", mib, &miblen), 0,
|
||||||
@@ -17,8 +17,8 @@ TEST_BEGIN(test_overflow)
|
|||||||
mib[2] = nhchunks - 1;
|
mib[2] = nhchunks - 1;
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &max_size_class, &sz, NULL, 0), 0,
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&max_size_class, &sz,
|
||||||
"Unexpected mallctlbymib() error");
|
NULL, 0), 0, "Unexpected mallctlbymib() error");
|
||||||
|
|
||||||
assert_ptr_null(malloc(max_size_class + 1),
|
assert_ptr_null(malloc(max_size_class + 1),
|
||||||
"Expected OOM due to over-sized allocation request");
|
"Expected OOM due to over-sized allocation request");
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
#include "test/jemalloc_test.h"
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
#define CHUNK 0x400000
|
#define CHUNK 0x400000
|
||||||
/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */
|
#define MAXALIGN (((size_t)1) << 23)
|
||||||
#define MAXALIGN ((size_t)0x2000000LU)
|
|
||||||
#define NITER 4
|
/*
|
||||||
|
* On systems which can't merge extents, tests that call this function generate
|
||||||
|
* a lot of dirty memory very quickly. Purging between cycles mitigates
|
||||||
|
* potential OOM on e.g. 32-bit Windows.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
purge(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
||||||
|
"Unexpected mallctl error");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_BEGIN(test_alignment_errors)
|
TEST_BEGIN(test_alignment_errors)
|
||||||
{
|
{
|
||||||
@@ -66,6 +77,7 @@ TEST_END
|
|||||||
|
|
||||||
TEST_BEGIN(test_alignment_and_size)
|
TEST_BEGIN(test_alignment_and_size)
|
||||||
{
|
{
|
||||||
|
#define NITER 4
|
||||||
size_t alignment, size, total;
|
size_t alignment, size, total;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int err;
|
int err;
|
||||||
@@ -104,7 +116,9 @@ TEST_BEGIN(test_alignment_and_size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
purge();
|
||||||
}
|
}
|
||||||
|
#undef NITER
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
|
|||||||
4
test/integration/rallocx.c
Normal file → Executable file
4
test/integration/rallocx.c
Normal file → Executable file
@@ -7,7 +7,7 @@ get_nsizes_impl(const char *cmd)
|
|||||||
size_t z;
|
size_t z;
|
||||||
|
|
||||||
z = sizeof(unsigned);
|
z = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,
|
assert_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0,
|
||||||
"Unexpected mallctl(\"%s\", ...) failure", cmd);
|
"Unexpected mallctl(\"%s\", ...) failure", cmd);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -33,7 +33,7 @@ get_size_impl(const char *cmd, size_t ind)
|
|||||||
0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
|
0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
|
||||||
mib[2] = ind;
|
mib[2] = ind;
|
||||||
z = sizeof(size_t);
|
z = sizeof(size_t);
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0),
|
||||||
0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
|
0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "test/jemalloc_test.h"
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
#define MAXALIGN (((size_t)1) << 25)
|
#define MAXALIGN (((size_t)1) << 22)
|
||||||
#define NITER 4
|
#define NITER 3
|
||||||
|
|
||||||
TEST_BEGIN(test_basic)
|
TEST_BEGIN(test_basic)
|
||||||
{
|
{
|
||||||
|
|||||||
10
test/integration/thread_arena.c
Normal file → Executable file
10
test/integration/thread_arena.c
Normal file → Executable file
@@ -16,8 +16,8 @@ thd_start(void *arg)
|
|||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
size = sizeof(arena_ind);
|
size = sizeof(arena_ind);
|
||||||
if ((err = mallctl("thread.arena", &arena_ind, &size, &main_arena_ind,
|
if ((err = mallctl("thread.arena", (void *)&arena_ind, &size,
|
||||||
sizeof(main_arena_ind)))) {
|
(void *)&main_arena_ind, sizeof(main_arena_ind)))) {
|
||||||
char buf[BUFERROR_BUF];
|
char buf[BUFERROR_BUF];
|
||||||
|
|
||||||
buferror(err, buf, sizeof(buf));
|
buferror(err, buf, sizeof(buf));
|
||||||
@@ -25,7 +25,8 @@ thd_start(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size = sizeof(arena_ind);
|
size = sizeof(arena_ind);
|
||||||
if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) {
|
if ((err = mallctl("thread.arena", (void *)&arena_ind, &size, NULL,
|
||||||
|
0))) {
|
||||||
char buf[BUFERROR_BUF];
|
char buf[BUFERROR_BUF];
|
||||||
|
|
||||||
buferror(err, buf, sizeof(buf));
|
buferror(err, buf, sizeof(buf));
|
||||||
@@ -50,7 +51,8 @@ TEST_BEGIN(test_thread_arena)
|
|||||||
assert_ptr_not_null(p, "Error in malloc()");
|
assert_ptr_not_null(p, "Error in malloc()");
|
||||||
|
|
||||||
size = sizeof(arena_ind);
|
size = sizeof(arena_ind);
|
||||||
if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) {
|
if ((err = mallctl("thread.arena", (void *)&arena_ind, &size, NULL,
|
||||||
|
0))) {
|
||||||
char buf[BUFERROR_BUF];
|
char buf[BUFERROR_BUF];
|
||||||
|
|
||||||
buferror(err, buf, sizeof(buf));
|
buferror(err, buf, sizeof(buf));
|
||||||
|
|||||||
39
test/integration/thread_tcache_enabled.c
Normal file → Executable file
39
test/integration/thread_tcache_enabled.c
Normal file → Executable file
@@ -16,7 +16,8 @@ thd_start(void *arg)
|
|||||||
bool e0, e1;
|
bool e0, e1;
|
||||||
|
|
||||||
sz = sizeof(bool);
|
sz = sizeof(bool);
|
||||||
if ((err = mallctl("thread.tcache.enabled", &e0, &sz, NULL, 0))) {
|
if ((err = mallctl("thread.tcache.enabled", (void *)&e0, &sz, NULL,
|
||||||
|
0))) {
|
||||||
if (err == ENOENT) {
|
if (err == ENOENT) {
|
||||||
assert_false(config_tcache,
|
assert_false(config_tcache,
|
||||||
"ENOENT should only be returned if tcache is "
|
"ENOENT should only be returned if tcache is "
|
||||||
@@ -27,53 +28,53 @@ thd_start(void *arg)
|
|||||||
|
|
||||||
if (e0) {
|
if (e0) {
|
||||||
e1 = false;
|
e1 = false;
|
||||||
assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz),
|
assert_d_eq(mallctl("thread.tcache.enabled", (void *)&e0, &sz,
|
||||||
0, "Unexpected mallctl() error");
|
(void *)&e1, sz), 0, "Unexpected mallctl() error");
|
||||||
assert_true(e0, "tcache should be enabled");
|
assert_true(e0, "tcache should be enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
e1 = true;
|
e1 = true;
|
||||||
assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
|
assert_d_eq(mallctl("thread.tcache.enabled", (void *)&e0, &sz,
|
||||||
"Unexpected mallctl() error");
|
(void *)&e1, sz), 0, "Unexpected mallctl() error");
|
||||||
assert_false(e0, "tcache should be disabled");
|
assert_false(e0, "tcache should be disabled");
|
||||||
|
|
||||||
e1 = true;
|
e1 = true;
|
||||||
assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
|
assert_d_eq(mallctl("thread.tcache.enabled", (void *)&e0, &sz,
|
||||||
"Unexpected mallctl() error");
|
(void *)&e1, sz), 0, "Unexpected mallctl() error");
|
||||||
assert_true(e0, "tcache should be enabled");
|
assert_true(e0, "tcache should be enabled");
|
||||||
|
|
||||||
e1 = false;
|
e1 = false;
|
||||||
assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
|
assert_d_eq(mallctl("thread.tcache.enabled", (void *)&e0, &sz,
|
||||||
"Unexpected mallctl() error");
|
(void *)&e1, sz), 0, "Unexpected mallctl() error");
|
||||||
assert_true(e0, "tcache should be enabled");
|
assert_true(e0, "tcache should be enabled");
|
||||||
|
|
||||||
e1 = false;
|
e1 = false;
|
||||||
assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
|
assert_d_eq(mallctl("thread.tcache.enabled", (void *)&e0, &sz,
|
||||||
"Unexpected mallctl() error");
|
(void *)&e1, sz), 0, "Unexpected mallctl() error");
|
||||||
assert_false(e0, "tcache should be disabled");
|
assert_false(e0, "tcache should be disabled");
|
||||||
|
|
||||||
free(malloc(1));
|
free(malloc(1));
|
||||||
e1 = true;
|
e1 = true;
|
||||||
assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
|
assert_d_eq(mallctl("thread.tcache.enabled", (void *)&e0, &sz,
|
||||||
"Unexpected mallctl() error");
|
(void *)&e1, sz), 0, "Unexpected mallctl() error");
|
||||||
assert_false(e0, "tcache should be disabled");
|
assert_false(e0, "tcache should be disabled");
|
||||||
|
|
||||||
free(malloc(1));
|
free(malloc(1));
|
||||||
e1 = true;
|
e1 = true;
|
||||||
assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
|
assert_d_eq(mallctl("thread.tcache.enabled", (void *)&e0, &sz,
|
||||||
"Unexpected mallctl() error");
|
(void *)&e1, sz), 0, "Unexpected mallctl() error");
|
||||||
assert_true(e0, "tcache should be enabled");
|
assert_true(e0, "tcache should be enabled");
|
||||||
|
|
||||||
free(malloc(1));
|
free(malloc(1));
|
||||||
e1 = false;
|
e1 = false;
|
||||||
assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
|
assert_d_eq(mallctl("thread.tcache.enabled", (void *)&e0, &sz,
|
||||||
"Unexpected mallctl() error");
|
(void *)&e1, sz), 0, "Unexpected mallctl() error");
|
||||||
assert_true(e0, "tcache should be enabled");
|
assert_true(e0, "tcache should be enabled");
|
||||||
|
|
||||||
free(malloc(1));
|
free(malloc(1));
|
||||||
e1 = false;
|
e1 = false;
|
||||||
assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0,
|
assert_d_eq(mallctl("thread.tcache.enabled", (void *)&e0, &sz,
|
||||||
"Unexpected mallctl() error");
|
(void *)&e1, sz), 0, "Unexpected mallctl() error");
|
||||||
assert_false(e0, "tcache should be disabled");
|
assert_false(e0, "tcache should be disabled");
|
||||||
|
|
||||||
free(malloc(1));
|
free(malloc(1));
|
||||||
|
|||||||
8
test/integration/xallocx.c
Normal file → Executable file
8
test/integration/xallocx.c
Normal file → Executable file
@@ -16,8 +16,8 @@ arena_ind(void)
|
|||||||
|
|
||||||
if (ind == 0) {
|
if (ind == 0) {
|
||||||
size_t sz = sizeof(ind);
|
size_t sz = sizeof(ind);
|
||||||
assert_d_eq(mallctl("arenas.extend", &ind, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.extend", (void *)&ind, &sz, NULL,
|
||||||
"Unexpected mallctl failure creating arena");
|
0), 0, "Unexpected mallctl failure creating arena");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ind);
|
return (ind);
|
||||||
@@ -78,7 +78,7 @@ get_nsizes_impl(const char *cmd)
|
|||||||
size_t z;
|
size_t z;
|
||||||
|
|
||||||
z = sizeof(unsigned);
|
z = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,
|
assert_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0,
|
||||||
"Unexpected mallctl(\"%s\", ...) failure", cmd);
|
"Unexpected mallctl(\"%s\", ...) failure", cmd);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -118,7 +118,7 @@ get_size_impl(const char *cmd, size_t ind)
|
|||||||
0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
|
0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
|
||||||
mib[2] = ind;
|
mib[2] = ind;
|
||||||
z = sizeof(size_t);
|
z = sizeof(size_t);
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0),
|
||||||
0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
|
0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ mtx_init(mtx_t *mtx)
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!InitializeCriticalSectionAndSpinCount(&mtx->lock, _CRT_SPINCOUNT))
|
if (!InitializeCriticalSectionAndSpinCount(&mtx->lock, _CRT_SPINCOUNT))
|
||||||
return (true);
|
return (true);
|
||||||
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
||||||
|
mtx->lock = OS_UNFAIR_LOCK_INIT;
|
||||||
#elif (defined(JEMALLOC_OSSPIN))
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
mtx->lock = 0;
|
mtx->lock = 0;
|
||||||
#else
|
#else
|
||||||
@@ -33,6 +35,7 @@ mtx_fini(mtx_t *mtx)
|
|||||||
{
|
{
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
||||||
#elif (defined(JEMALLOC_OSSPIN))
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
#else
|
#else
|
||||||
pthread_mutex_destroy(&mtx->lock);
|
pthread_mutex_destroy(&mtx->lock);
|
||||||
@@ -45,6 +48,8 @@ mtx_lock(mtx_t *mtx)
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
EnterCriticalSection(&mtx->lock);
|
EnterCriticalSection(&mtx->lock);
|
||||||
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
||||||
|
os_unfair_lock_lock(&mtx->lock);
|
||||||
#elif (defined(JEMALLOC_OSSPIN))
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
OSSpinLockLock(&mtx->lock);
|
OSSpinLockLock(&mtx->lock);
|
||||||
#else
|
#else
|
||||||
@@ -58,6 +63,8 @@ mtx_unlock(mtx_t *mtx)
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
LeaveCriticalSection(&mtx->lock);
|
LeaveCriticalSection(&mtx->lock);
|
||||||
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
||||||
|
os_unfair_lock_unlock(&mtx->lock);
|
||||||
#elif (defined(JEMALLOC_OSSPIN))
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
OSSpinLockUnlock(&mtx->lock);
|
OSSpinLockUnlock(&mtx->lock);
|
||||||
#else
|
#else
|
||||||
|
|||||||
8
test/unit/arena_reset.c
Normal file → Executable file
8
test/unit/arena_reset.c
Normal file → Executable file
@@ -11,7 +11,7 @@ get_nsizes_impl(const char *cmd)
|
|||||||
size_t z;
|
size_t z;
|
||||||
|
|
||||||
z = sizeof(unsigned);
|
z = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,
|
assert_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0,
|
||||||
"Unexpected mallctl(\"%s\", ...) failure", cmd);
|
"Unexpected mallctl(\"%s\", ...) failure", cmd);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -51,7 +51,7 @@ get_size_impl(const char *cmd, size_t ind)
|
|||||||
0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
|
0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
|
||||||
mib[2] = ind;
|
mib[2] = ind;
|
||||||
z = sizeof(size_t);
|
z = sizeof(size_t);
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0),
|
||||||
0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
|
0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -92,8 +92,8 @@ TEST_BEGIN(test_arena_reset)
|
|||||||
&& unlikely(opt_quarantine)));
|
&& unlikely(opt_quarantine)));
|
||||||
|
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.extend", (void *)&arena_ind, &sz, NULL, 0),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;
|
flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;
|
||||||
|
|
||||||
|
|||||||
@@ -2,24 +2,24 @@
|
|||||||
|
|
||||||
TEST_BEGIN(test_new_delete)
|
TEST_BEGIN(test_new_delete)
|
||||||
{
|
{
|
||||||
tsdn_t *tsdn;
|
tsd_t *tsd;
|
||||||
ckh_t ckh;
|
ckh_t ckh;
|
||||||
|
|
||||||
tsdn = tsdn_fetch();
|
tsd = tsd_fetch();
|
||||||
|
|
||||||
assert_false(ckh_new(tsdn, &ckh, 2, ckh_string_hash,
|
assert_false(ckh_new(tsd, &ckh, 2, ckh_string_hash,
|
||||||
ckh_string_keycomp), "Unexpected ckh_new() error");
|
ckh_string_keycomp), "Unexpected ckh_new() error");
|
||||||
ckh_delete(tsdn, &ckh);
|
ckh_delete(tsd, &ckh);
|
||||||
|
|
||||||
assert_false(ckh_new(tsdn, &ckh, 3, ckh_pointer_hash,
|
assert_false(ckh_new(tsd, &ckh, 3, ckh_pointer_hash,
|
||||||
ckh_pointer_keycomp), "Unexpected ckh_new() error");
|
ckh_pointer_keycomp), "Unexpected ckh_new() error");
|
||||||
ckh_delete(tsdn, &ckh);
|
ckh_delete(tsd, &ckh);
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
TEST_BEGIN(test_count_insert_search_remove)
|
TEST_BEGIN(test_count_insert_search_remove)
|
||||||
{
|
{
|
||||||
tsdn_t *tsdn;
|
tsd_t *tsd;
|
||||||
ckh_t ckh;
|
ckh_t ckh;
|
||||||
const char *strs[] = {
|
const char *strs[] = {
|
||||||
"a string",
|
"a string",
|
||||||
@@ -30,9 +30,9 @@ TEST_BEGIN(test_count_insert_search_remove)
|
|||||||
const char *missing = "A string not in the hash table.";
|
const char *missing = "A string not in the hash table.";
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
tsdn = tsdn_fetch();
|
tsd = tsd_fetch();
|
||||||
|
|
||||||
assert_false(ckh_new(tsdn, &ckh, 2, ckh_string_hash,
|
assert_false(ckh_new(tsd, &ckh, 2, ckh_string_hash,
|
||||||
ckh_string_keycomp), "Unexpected ckh_new() error");
|
ckh_string_keycomp), "Unexpected ckh_new() error");
|
||||||
assert_zu_eq(ckh_count(&ckh), 0,
|
assert_zu_eq(ckh_count(&ckh), 0,
|
||||||
"ckh_count() should return %zu, but it returned %zu", ZU(0),
|
"ckh_count() should return %zu, but it returned %zu", ZU(0),
|
||||||
@@ -40,7 +40,7 @@ TEST_BEGIN(test_count_insert_search_remove)
|
|||||||
|
|
||||||
/* Insert. */
|
/* Insert. */
|
||||||
for (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {
|
for (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {
|
||||||
ckh_insert(tsdn, &ckh, strs[i], strs[i]);
|
ckh_insert(tsd, &ckh, strs[i], strs[i]);
|
||||||
assert_zu_eq(ckh_count(&ckh), i+1,
|
assert_zu_eq(ckh_count(&ckh), i+1,
|
||||||
"ckh_count() should return %zu, but it returned %zu", i+1,
|
"ckh_count() should return %zu, but it returned %zu", i+1,
|
||||||
ckh_count(&ckh));
|
ckh_count(&ckh));
|
||||||
@@ -85,7 +85,7 @@ TEST_BEGIN(test_count_insert_search_remove)
|
|||||||
vp = (i & 2) ? &v.p : NULL;
|
vp = (i & 2) ? &v.p : NULL;
|
||||||
k.p = NULL;
|
k.p = NULL;
|
||||||
v.p = NULL;
|
v.p = NULL;
|
||||||
assert_false(ckh_remove(tsdn, &ckh, strs[i], kp, vp),
|
assert_false(ckh_remove(tsd, &ckh, strs[i], kp, vp),
|
||||||
"Unexpected ckh_remove() error");
|
"Unexpected ckh_remove() error");
|
||||||
|
|
||||||
ks = (i & 1) ? strs[i] : (const char *)NULL;
|
ks = (i & 1) ? strs[i] : (const char *)NULL;
|
||||||
@@ -101,22 +101,22 @@ TEST_BEGIN(test_count_insert_search_remove)
|
|||||||
ckh_count(&ckh));
|
ckh_count(&ckh));
|
||||||
}
|
}
|
||||||
|
|
||||||
ckh_delete(tsdn, &ckh);
|
ckh_delete(tsd, &ckh);
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
TEST_BEGIN(test_insert_iter_remove)
|
TEST_BEGIN(test_insert_iter_remove)
|
||||||
{
|
{
|
||||||
#define NITEMS ZU(1000)
|
#define NITEMS ZU(1000)
|
||||||
tsdn_t *tsdn;
|
tsd_t *tsd;
|
||||||
ckh_t ckh;
|
ckh_t ckh;
|
||||||
void **p[NITEMS];
|
void **p[NITEMS];
|
||||||
void *q, *r;
|
void *q, *r;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
tsdn = tsdn_fetch();
|
tsd = tsd_fetch();
|
||||||
|
|
||||||
assert_false(ckh_new(tsdn, &ckh, 2, ckh_pointer_hash,
|
assert_false(ckh_new(tsd, &ckh, 2, ckh_pointer_hash,
|
||||||
ckh_pointer_keycomp), "Unexpected ckh_new() error");
|
ckh_pointer_keycomp), "Unexpected ckh_new() error");
|
||||||
|
|
||||||
for (i = 0; i < NITEMS; i++) {
|
for (i = 0; i < NITEMS; i++) {
|
||||||
@@ -128,7 +128,7 @@ TEST_BEGIN(test_insert_iter_remove)
|
|||||||
size_t j;
|
size_t j;
|
||||||
|
|
||||||
for (j = i; j < NITEMS; j++) {
|
for (j = i; j < NITEMS; j++) {
|
||||||
assert_false(ckh_insert(tsdn, &ckh, p[j], p[j]),
|
assert_false(ckh_insert(tsd, &ckh, p[j], p[j]),
|
||||||
"Unexpected ckh_insert() failure");
|
"Unexpected ckh_insert() failure");
|
||||||
assert_false(ckh_search(&ckh, p[j], &q, &r),
|
assert_false(ckh_search(&ckh, p[j], &q, &r),
|
||||||
"Unexpected ckh_search() failure");
|
"Unexpected ckh_search() failure");
|
||||||
@@ -143,13 +143,13 @@ TEST_BEGIN(test_insert_iter_remove)
|
|||||||
for (j = i + 1; j < NITEMS; j++) {
|
for (j = i + 1; j < NITEMS; j++) {
|
||||||
assert_false(ckh_search(&ckh, p[j], NULL, NULL),
|
assert_false(ckh_search(&ckh, p[j], NULL, NULL),
|
||||||
"Unexpected ckh_search() failure");
|
"Unexpected ckh_search() failure");
|
||||||
assert_false(ckh_remove(tsdn, &ckh, p[j], &q, &r),
|
assert_false(ckh_remove(tsd, &ckh, p[j], &q, &r),
|
||||||
"Unexpected ckh_remove() failure");
|
"Unexpected ckh_remove() failure");
|
||||||
assert_ptr_eq(p[j], q, "Key pointer mismatch");
|
assert_ptr_eq(p[j], q, "Key pointer mismatch");
|
||||||
assert_ptr_eq(p[j], r, "Value pointer mismatch");
|
assert_ptr_eq(p[j], r, "Value pointer mismatch");
|
||||||
assert_true(ckh_search(&ckh, p[j], NULL, NULL),
|
assert_true(ckh_search(&ckh, p[j], NULL, NULL),
|
||||||
"Unexpected ckh_search() success");
|
"Unexpected ckh_search() success");
|
||||||
assert_true(ckh_remove(tsdn, &ckh, p[j], &q, &r),
|
assert_true(ckh_remove(tsd, &ckh, p[j], &q, &r),
|
||||||
"Unexpected ckh_remove() success");
|
"Unexpected ckh_remove() success");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,13 +184,13 @@ TEST_BEGIN(test_insert_iter_remove)
|
|||||||
for (i = 0; i < NITEMS; i++) {
|
for (i = 0; i < NITEMS; i++) {
|
||||||
assert_false(ckh_search(&ckh, p[i], NULL, NULL),
|
assert_false(ckh_search(&ckh, p[i], NULL, NULL),
|
||||||
"Unexpected ckh_search() failure");
|
"Unexpected ckh_search() failure");
|
||||||
assert_false(ckh_remove(tsdn, &ckh, p[i], &q, &r),
|
assert_false(ckh_remove(tsd, &ckh, p[i], &q, &r),
|
||||||
"Unexpected ckh_remove() failure");
|
"Unexpected ckh_remove() failure");
|
||||||
assert_ptr_eq(p[i], q, "Key pointer mismatch");
|
assert_ptr_eq(p[i], q, "Key pointer mismatch");
|
||||||
assert_ptr_eq(p[i], r, "Value pointer mismatch");
|
assert_ptr_eq(p[i], r, "Value pointer mismatch");
|
||||||
assert_true(ckh_search(&ckh, p[i], NULL, NULL),
|
assert_true(ckh_search(&ckh, p[i], NULL, NULL),
|
||||||
"Unexpected ckh_search() success");
|
"Unexpected ckh_search() success");
|
||||||
assert_true(ckh_remove(tsdn, &ckh, p[i], &q, &r),
|
assert_true(ckh_remove(tsd, &ckh, p[i], &q, &r),
|
||||||
"Unexpected ckh_remove() success");
|
"Unexpected ckh_remove() success");
|
||||||
dallocx(p[i], 0);
|
dallocx(p[i], 0);
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ TEST_BEGIN(test_insert_iter_remove)
|
|||||||
assert_zu_eq(ckh_count(&ckh), 0,
|
assert_zu_eq(ckh_count(&ckh), 0,
|
||||||
"ckh_count() should return %zu, but it returned %zu",
|
"ckh_count() should return %zu, but it returned %zu",
|
||||||
ZU(0), ckh_count(&ckh));
|
ZU(0), ckh_count(&ckh));
|
||||||
ckh_delete(tsdn, &ckh);
|
ckh_delete(tsd, &ckh);
|
||||||
#undef NITEMS
|
#undef NITEMS
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|||||||
82
test/unit/decay.c
Normal file → Executable file
82
test/unit/decay.c
Normal file → Executable file
@@ -2,20 +2,28 @@
|
|||||||
|
|
||||||
const char *malloc_conf = "purge:decay,decay_time:1";
|
const char *malloc_conf = "purge:decay,decay_time:1";
|
||||||
|
|
||||||
|
static nstime_monotonic_t *nstime_monotonic_orig;
|
||||||
static nstime_update_t *nstime_update_orig;
|
static nstime_update_t *nstime_update_orig;
|
||||||
|
|
||||||
static unsigned nupdates_mock;
|
static unsigned nupdates_mock;
|
||||||
static nstime_t time_mock;
|
static nstime_t time_mock;
|
||||||
static bool nonmonotonic_mock;
|
static bool monotonic_mock;
|
||||||
|
|
||||||
|
static bool
|
||||||
|
nstime_monotonic_mock(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (monotonic_mock);
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
nstime_update_mock(nstime_t *time)
|
nstime_update_mock(nstime_t *time)
|
||||||
{
|
{
|
||||||
|
|
||||||
nupdates_mock++;
|
nupdates_mock++;
|
||||||
if (!nonmonotonic_mock)
|
if (monotonic_mock)
|
||||||
nstime_copy(time, &time_mock);
|
nstime_copy(time, &time_mock);
|
||||||
return (nonmonotonic_mock);
|
return (!monotonic_mock);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_BEGIN(test_decay_ticks)
|
TEST_BEGIN(test_decay_ticks)
|
||||||
@@ -32,10 +40,10 @@ TEST_BEGIN(test_decay_ticks)
|
|||||||
"Unexpected failure getting decay ticker");
|
"Unexpected failure getting decay ticker");
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("arenas.hchunk.0.size", &huge0, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.hchunk.0.size", (void *)&huge0, &sz, NULL,
|
||||||
"Unexpected mallctl failure");
|
0), 0, "Unexpected mallctl failure");
|
||||||
assert_d_eq(mallctl("arenas.lrun.0.size", &large0, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.lrun.0.size", (void *)&large0, &sz, NULL,
|
||||||
"Unexpected mallctl failure");
|
0), 0, "Unexpected mallctl failure");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test the standard APIs using a huge size class, since we can't
|
* Test the standard APIs using a huge size class, since we can't
|
||||||
@@ -167,8 +175,8 @@ TEST_BEGIN(test_decay_ticks)
|
|||||||
tcache_sizes[1] = 1;
|
tcache_sizes[1] = 1;
|
||||||
|
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("tcache.create", &tcache_ind, &sz, NULL, 0),
|
assert_d_eq(mallctl("tcache.create", (void *)&tcache_ind, &sz,
|
||||||
0, "Unexpected mallctl failure");
|
NULL, 0), 0, "Unexpected mallctl failure");
|
||||||
|
|
||||||
for (i = 0; i < sizeof(tcache_sizes) / sizeof(size_t); i++) {
|
for (i = 0; i < sizeof(tcache_sizes) / sizeof(size_t); i++) {
|
||||||
sz = tcache_sizes[i];
|
sz = tcache_sizes[i];
|
||||||
@@ -185,7 +193,7 @@ TEST_BEGIN(test_decay_ticks)
|
|||||||
dallocx(p, MALLOCX_TCACHE(tcache_ind));
|
dallocx(p, MALLOCX_TCACHE(tcache_ind));
|
||||||
tick0 = ticker_read(decay_ticker);
|
tick0 = ticker_read(decay_ticker);
|
||||||
assert_d_eq(mallctl("tcache.flush", NULL, NULL,
|
assert_d_eq(mallctl("tcache.flush", NULL, NULL,
|
||||||
&tcache_ind, sizeof(unsigned)), 0,
|
(void *)&tcache_ind, sizeof(unsigned)), 0,
|
||||||
"Unexpected mallctl failure");
|
"Unexpected mallctl failure");
|
||||||
tick1 = ticker_read(decay_ticker);
|
tick1 = ticker_read(decay_ticker);
|
||||||
assert_u32_ne(tick1, tick0,
|
assert_u32_ne(tick1, tick0,
|
||||||
@@ -220,22 +228,22 @@ TEST_BEGIN(test_decay_ticker)
|
|||||||
size_t tcache_max;
|
size_t tcache_max;
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("arenas.tcache_max", &tcache_max, &sz, NULL,
|
assert_d_eq(mallctl("arenas.tcache_max", (void *)&tcache_max,
|
||||||
0), 0, "Unexpected mallctl failure");
|
&sz, NULL, 0), 0, "Unexpected mallctl failure");
|
||||||
large = nallocx(tcache_max + 1, flags);
|
large = nallocx(tcache_max + 1, flags);
|
||||||
} else {
|
} else {
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("arenas.lrun.0.size", &large, &sz, NULL, 0),
|
assert_d_eq(mallctl("arenas.lrun.0.size", (void *)&large, &sz,
|
||||||
0, "Unexpected mallctl failure");
|
NULL, 0), 0, "Unexpected mallctl failure");
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
||||||
"Unexpected mallctl failure");
|
"Unexpected mallctl failure");
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(uint64_t)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
|
||||||
"Unexpected mallctl failure");
|
sizeof(uint64_t)), 0, "Unexpected mallctl failure");
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.npurge", &npurge0, &sz, NULL, 0),
|
assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge0, &sz,
|
||||||
config_stats ? 0 : ENOENT, "Unexpected mallctl result");
|
NULL, 0), config_stats ? 0 : ENOENT, "Unexpected mallctl result");
|
||||||
|
|
||||||
for (i = 0; i < NPS; i++) {
|
for (i = 0; i < NPS; i++) {
|
||||||
ps[i] = mallocx(large, flags);
|
ps[i] = mallocx(large, flags);
|
||||||
@@ -245,9 +253,11 @@ TEST_BEGIN(test_decay_ticker)
|
|||||||
nupdates_mock = 0;
|
nupdates_mock = 0;
|
||||||
nstime_init(&time_mock, 0);
|
nstime_init(&time_mock, 0);
|
||||||
nstime_update(&time_mock);
|
nstime_update(&time_mock);
|
||||||
nonmonotonic_mock = false;
|
monotonic_mock = true;
|
||||||
|
|
||||||
|
nstime_monotonic_orig = nstime_monotonic;
|
||||||
nstime_update_orig = nstime_update;
|
nstime_update_orig = nstime_update;
|
||||||
|
nstime_monotonic = nstime_monotonic_mock;
|
||||||
nstime_update = nstime_update_mock;
|
nstime_update = nstime_update_mock;
|
||||||
|
|
||||||
for (i = 0; i < NPS; i++) {
|
for (i = 0; i < NPS; i++) {
|
||||||
@@ -259,6 +269,7 @@ TEST_BEGIN(test_decay_ticker)
|
|||||||
"Expected nstime_update() to be called");
|
"Expected nstime_update() to be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nstime_monotonic = nstime_monotonic_orig;
|
||||||
nstime_update = nstime_update_orig;
|
nstime_update = nstime_update_orig;
|
||||||
|
|
||||||
nstime_init(&time, 0);
|
nstime_init(&time, 0);
|
||||||
@@ -272,11 +283,11 @@ TEST_BEGIN(test_decay_ticker)
|
|||||||
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
||||||
dallocx(p, flags);
|
dallocx(p, flags);
|
||||||
}
|
}
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
|
||||||
sizeof(uint64_t)), 0, "Unexpected mallctl failure");
|
sizeof(uint64_t)), 0, "Unexpected mallctl failure");
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.npurge", &npurge1, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge1,
|
||||||
NULL, 0), config_stats ? 0 : ENOENT,
|
&sz, NULL, 0), config_stats ? 0 : ENOENT,
|
||||||
"Unexpected mallctl result");
|
"Unexpected mallctl result");
|
||||||
|
|
||||||
nstime_update(&time);
|
nstime_update(&time);
|
||||||
@@ -302,23 +313,25 @@ TEST_BEGIN(test_decay_nonmonotonic)
|
|||||||
test_skip_if(opt_purge != purge_mode_decay);
|
test_skip_if(opt_purge != purge_mode_decay);
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("arenas.lrun.0.size", &large0, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.lrun.0.size", (void *)&large0, &sz, NULL,
|
||||||
"Unexpected mallctl failure");
|
0), 0, "Unexpected mallctl failure");
|
||||||
|
|
||||||
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
||||||
"Unexpected mallctl failure");
|
"Unexpected mallctl failure");
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(uint64_t)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
|
||||||
"Unexpected mallctl failure");
|
sizeof(uint64_t)), 0, "Unexpected mallctl failure");
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.npurge", &npurge0, &sz, NULL, 0),
|
assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge0, &sz,
|
||||||
config_stats ? 0 : ENOENT, "Unexpected mallctl result");
|
NULL, 0), config_stats ? 0 : ENOENT, "Unexpected mallctl result");
|
||||||
|
|
||||||
nupdates_mock = 0;
|
nupdates_mock = 0;
|
||||||
nstime_init(&time_mock, 0);
|
nstime_init(&time_mock, 0);
|
||||||
nstime_update(&time_mock);
|
nstime_update(&time_mock);
|
||||||
nonmonotonic_mock = true;
|
monotonic_mock = false;
|
||||||
|
|
||||||
|
nstime_monotonic_orig = nstime_monotonic;
|
||||||
nstime_update_orig = nstime_update;
|
nstime_update_orig = nstime_update;
|
||||||
|
nstime_monotonic = nstime_monotonic_mock;
|
||||||
nstime_update = nstime_update_mock;
|
nstime_update = nstime_update_mock;
|
||||||
|
|
||||||
for (i = 0; i < NPS; i++) {
|
for (i = 0; i < NPS; i++) {
|
||||||
@@ -335,15 +348,16 @@ TEST_BEGIN(test_decay_nonmonotonic)
|
|||||||
"Expected nstime_update() to be called");
|
"Expected nstime_update() to be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(uint64_t)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
|
||||||
"Unexpected mallctl failure");
|
sizeof(uint64_t)), 0, "Unexpected mallctl failure");
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.npurge", &npurge1, &sz, NULL, 0),
|
assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge1, &sz,
|
||||||
config_stats ? 0 : ENOENT, "Unexpected mallctl result");
|
NULL, 0), config_stats ? 0 : ENOENT, "Unexpected mallctl result");
|
||||||
|
|
||||||
if (config_stats)
|
if (config_stats)
|
||||||
assert_u64_gt(npurge1, npurge0, "Expected purging to occur");
|
assert_u64_eq(npurge0, npurge1, "Unexpected purging occurred");
|
||||||
|
|
||||||
|
nstime_monotonic = nstime_monotonic_orig;
|
||||||
nstime_update = nstime_update_orig;
|
nstime_update = nstime_update_orig;
|
||||||
#undef NPS
|
#undef NPS
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ TEST_BEGIN(test_fork)
|
|||||||
test_fail("Unexpected fork() failure");
|
test_fail("Unexpected fork() failure");
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
/* Child. */
|
/* Child. */
|
||||||
exit(0);
|
_exit(0);
|
||||||
} else {
|
} else {
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
|||||||
@@ -53,10 +53,10 @@ arena_dalloc_junk_large_intercept(void *ptr, size_t usize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
huge_dalloc_junk_intercept(tsdn_t *tsdn, void *ptr, size_t usize)
|
huge_dalloc_junk_intercept(void *ptr, size_t usize)
|
||||||
{
|
{
|
||||||
|
|
||||||
huge_dalloc_junk_orig(tsdn, ptr, usize);
|
huge_dalloc_junk_orig(ptr, usize);
|
||||||
/*
|
/*
|
||||||
* The conditions under which junk filling actually occurs are nuanced
|
* The conditions under which junk filling actually occurs are nuanced
|
||||||
* enough that it doesn't make sense to duplicate the decision logic in
|
* enough that it doesn't make sense to duplicate the decision logic in
|
||||||
|
|||||||
211
test/unit/mallctl.c
Normal file → Executable file
211
test/unit/mallctl.c
Normal file → Executable file
@@ -12,16 +12,18 @@ TEST_BEGIN(test_mallctl_errors)
|
|||||||
EPERM, "mallctl() should return EPERM on attempt to write "
|
EPERM, "mallctl() should return EPERM on attempt to write "
|
||||||
"read-only value");
|
"read-only value");
|
||||||
|
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)-1),
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
|
||||||
EINVAL, "mallctl() should return EINVAL for input size mismatch");
|
sizeof(epoch)-1), EINVAL,
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)+1),
|
"mallctl() should return EINVAL for input size mismatch");
|
||||||
EINVAL, "mallctl() should return EINVAL for input size mismatch");
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
|
||||||
|
sizeof(epoch)+1), EINVAL,
|
||||||
|
"mallctl() should return EINVAL for input size mismatch");
|
||||||
|
|
||||||
sz = sizeof(epoch)-1;
|
sz = sizeof(epoch)-1;
|
||||||
assert_d_eq(mallctl("epoch", &epoch, &sz, NULL, 0), EINVAL,
|
assert_d_eq(mallctl("epoch", (void *)&epoch, &sz, NULL, 0), EINVAL,
|
||||||
"mallctl() should return EINVAL for output size mismatch");
|
"mallctl() should return EINVAL for output size mismatch");
|
||||||
sz = sizeof(epoch)+1;
|
sz = sizeof(epoch)+1;
|
||||||
assert_d_eq(mallctl("epoch", &epoch, &sz, NULL, 0), EINVAL,
|
assert_d_eq(mallctl("epoch", (void *)&epoch, &sz, NULL, 0), EINVAL,
|
||||||
"mallctl() should return EINVAL for output size mismatch");
|
"mallctl() should return EINVAL for output size mismatch");
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
@@ -56,18 +58,20 @@ TEST_BEGIN(test_mallctlbymib_errors)
|
|||||||
assert_d_eq(mallctlnametomib("epoch", mib, &miblen), 0,
|
assert_d_eq(mallctlnametomib("epoch", mib, &miblen), 0,
|
||||||
"Unexpected mallctlnametomib() failure");
|
"Unexpected mallctlnametomib() failure");
|
||||||
|
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch,
|
assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&epoch,
|
||||||
sizeof(epoch)-1), EINVAL,
|
sizeof(epoch)-1), EINVAL,
|
||||||
"mallctlbymib() should return EINVAL for input size mismatch");
|
"mallctlbymib() should return EINVAL for input size mismatch");
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch,
|
assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&epoch,
|
||||||
sizeof(epoch)+1), EINVAL,
|
sizeof(epoch)+1), EINVAL,
|
||||||
"mallctlbymib() should return EINVAL for input size mismatch");
|
"mallctlbymib() should return EINVAL for input size mismatch");
|
||||||
|
|
||||||
sz = sizeof(epoch)-1;
|
sz = sizeof(epoch)-1;
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL,
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&epoch, &sz, NULL, 0),
|
||||||
|
EINVAL,
|
||||||
"mallctlbymib() should return EINVAL for output size mismatch");
|
"mallctlbymib() should return EINVAL for output size mismatch");
|
||||||
sz = sizeof(epoch)+1;
|
sz = sizeof(epoch)+1;
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL,
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&epoch, &sz, NULL, 0),
|
||||||
|
EINVAL,
|
||||||
"mallctlbymib() should return EINVAL for output size mismatch");
|
"mallctlbymib() should return EINVAL for output size mismatch");
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
@@ -83,18 +87,19 @@ TEST_BEGIN(test_mallctl_read_write)
|
|||||||
assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
|
assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
|
||||||
|
|
||||||
/* Read. */
|
/* Read. */
|
||||||
assert_d_eq(mallctl("epoch", &old_epoch, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("epoch", (void *)&old_epoch, &sz, NULL, 0), 0,
|
||||||
"Unexpected mallctl() failure");
|
"Unexpected mallctl() failure");
|
||||||
assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
|
assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
|
||||||
|
|
||||||
/* Write. */
|
/* Write. */
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &new_epoch, sizeof(new_epoch)),
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&new_epoch,
|
||||||
0, "Unexpected mallctl() failure");
|
sizeof(new_epoch)), 0, "Unexpected mallctl() failure");
|
||||||
assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
|
assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
|
||||||
|
|
||||||
/* Read+write. */
|
/* Read+write. */
|
||||||
assert_d_eq(mallctl("epoch", &old_epoch, &sz, &new_epoch,
|
assert_d_eq(mallctl("epoch", (void *)&old_epoch, &sz,
|
||||||
sizeof(new_epoch)), 0, "Unexpected mallctl() failure");
|
(void *)&new_epoch, sizeof(new_epoch)), 0,
|
||||||
|
"Unexpected mallctl() failure");
|
||||||
assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
|
assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
@@ -120,8 +125,8 @@ TEST_BEGIN(test_mallctl_config)
|
|||||||
#define TEST_MALLCTL_CONFIG(config, t) do { \
|
#define TEST_MALLCTL_CONFIG(config, t) do { \
|
||||||
t oldval; \
|
t oldval; \
|
||||||
size_t sz = sizeof(oldval); \
|
size_t sz = sizeof(oldval); \
|
||||||
assert_d_eq(mallctl("config."#config, &oldval, &sz, NULL, 0), \
|
assert_d_eq(mallctl("config."#config, (void *)&oldval, &sz, \
|
||||||
0, "Unexpected mallctl() failure"); \
|
NULL, 0), 0, "Unexpected mallctl() failure"); \
|
||||||
assert_b_eq(oldval, config_##config, "Incorrect config value"); \
|
assert_b_eq(oldval, config_##config, "Incorrect config value"); \
|
||||||
assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \
|
assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@@ -154,7 +159,8 @@ TEST_BEGIN(test_mallctl_opt)
|
|||||||
t oldval; \
|
t oldval; \
|
||||||
size_t sz = sizeof(oldval); \
|
size_t sz = sizeof(oldval); \
|
||||||
int expected = config_##config ? 0 : ENOENT; \
|
int expected = config_##config ? 0 : ENOENT; \
|
||||||
int result = mallctl("opt."#opt, &oldval, &sz, NULL, 0); \
|
int result = mallctl("opt."#opt, (void *)&oldval, &sz, NULL, \
|
||||||
|
0); \
|
||||||
assert_d_eq(result, expected, \
|
assert_d_eq(result, expected, \
|
||||||
"Unexpected mallctl() result for opt."#opt); \
|
"Unexpected mallctl() result for opt."#opt); \
|
||||||
assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \
|
assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \
|
||||||
@@ -197,7 +203,7 @@ TEST_BEGIN(test_manpage_example)
|
|||||||
size_t len, miblen;
|
size_t len, miblen;
|
||||||
|
|
||||||
len = sizeof(nbins);
|
len = sizeof(nbins);
|
||||||
assert_d_eq(mallctl("arenas.nbins", &nbins, &len, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.nbins", (void *)&nbins, &len, NULL, 0), 0,
|
||||||
"Unexpected mallctl() failure");
|
"Unexpected mallctl() failure");
|
||||||
|
|
||||||
miblen = 4;
|
miblen = 4;
|
||||||
@@ -208,8 +214,8 @@ TEST_BEGIN(test_manpage_example)
|
|||||||
|
|
||||||
mib[2] = i;
|
mib[2] = i;
|
||||||
len = sizeof(bin_size);
|
len = sizeof(bin_size);
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0),
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&bin_size, &len,
|
||||||
0, "Unexpected mallctlbymib() failure");
|
NULL, 0), 0, "Unexpected mallctlbymib() failure");
|
||||||
/* Do something with bin_size... */
|
/* Do something with bin_size... */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,25 +264,25 @@ TEST_BEGIN(test_tcache)
|
|||||||
/* Create tcaches. */
|
/* Create tcaches. */
|
||||||
for (i = 0; i < NTCACHES; i++) {
|
for (i = 0; i < NTCACHES; i++) {
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("tcache.create", &tis[i], &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("tcache.create", (void *)&tis[i], &sz, NULL,
|
||||||
"Unexpected mallctl() failure, i=%u", i);
|
0), 0, "Unexpected mallctl() failure, i=%u", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exercise tcache ID recycling. */
|
/* Exercise tcache ID recycling. */
|
||||||
for (i = 0; i < NTCACHES; i++) {
|
for (i = 0; i < NTCACHES; i++) {
|
||||||
assert_d_eq(mallctl("tcache.destroy", NULL, NULL, &tis[i],
|
assert_d_eq(mallctl("tcache.destroy", NULL, NULL,
|
||||||
sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
|
(void *)&tis[i], sizeof(unsigned)), 0,
|
||||||
i);
|
"Unexpected mallctl() failure, i=%u", i);
|
||||||
}
|
}
|
||||||
for (i = 0; i < NTCACHES; i++) {
|
for (i = 0; i < NTCACHES; i++) {
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("tcache.create", &tis[i], &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("tcache.create", (void *)&tis[i], &sz, NULL,
|
||||||
"Unexpected mallctl() failure, i=%u", i);
|
0), 0, "Unexpected mallctl() failure, i=%u", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush empty tcaches. */
|
/* Flush empty tcaches. */
|
||||||
for (i = 0; i < NTCACHES; i++) {
|
for (i = 0; i < NTCACHES; i++) {
|
||||||
assert_d_eq(mallctl("tcache.flush", NULL, NULL, &tis[i],
|
assert_d_eq(mallctl("tcache.flush", NULL, NULL, (void *)&tis[i],
|
||||||
sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
|
sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
|
||||||
i);
|
i);
|
||||||
}
|
}
|
||||||
@@ -321,16 +327,16 @@ TEST_BEGIN(test_tcache)
|
|||||||
|
|
||||||
/* Flush some non-empty tcaches. */
|
/* Flush some non-empty tcaches. */
|
||||||
for (i = 0; i < NTCACHES/2; i++) {
|
for (i = 0; i < NTCACHES/2; i++) {
|
||||||
assert_d_eq(mallctl("tcache.flush", NULL, NULL, &tis[i],
|
assert_d_eq(mallctl("tcache.flush", NULL, NULL, (void *)&tis[i],
|
||||||
sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
|
sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
|
||||||
i);
|
i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy tcaches. */
|
/* Destroy tcaches. */
|
||||||
for (i = 0; i < NTCACHES; i++) {
|
for (i = 0; i < NTCACHES; i++) {
|
||||||
assert_d_eq(mallctl("tcache.destroy", NULL, NULL, &tis[i],
|
assert_d_eq(mallctl("tcache.destroy", NULL, NULL,
|
||||||
sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
|
(void *)&tis[i], sizeof(unsigned)), 0,
|
||||||
i);
|
"Unexpected mallctl() failure, i=%u", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
@@ -340,15 +346,17 @@ TEST_BEGIN(test_thread_arena)
|
|||||||
unsigned arena_old, arena_new, narenas;
|
unsigned arena_old, arena_new, narenas;
|
||||||
size_t sz = sizeof(unsigned);
|
size_t sz = sizeof(unsigned);
|
||||||
|
|
||||||
assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
assert_u_eq(narenas, opt_narenas, "Number of arenas incorrect");
|
assert_u_eq(narenas, opt_narenas, "Number of arenas incorrect");
|
||||||
arena_new = narenas - 1;
|
arena_new = narenas - 1;
|
||||||
assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new,
|
assert_d_eq(mallctl("thread.arena", (void *)&arena_old, &sz,
|
||||||
sizeof(unsigned)), 0, "Unexpected mallctl() failure");
|
(void *)&arena_new, sizeof(unsigned)), 0,
|
||||||
|
"Unexpected mallctl() failure");
|
||||||
arena_new = 0;
|
arena_new = 0;
|
||||||
assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new,
|
assert_d_eq(mallctl("thread.arena", (void *)&arena_old, &sz,
|
||||||
sizeof(unsigned)), 0, "Unexpected mallctl() failure");
|
(void *)&arena_new, sizeof(unsigned)), 0,
|
||||||
|
"Unexpected mallctl() failure");
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
@@ -359,17 +367,18 @@ TEST_BEGIN(test_arena_i_lg_dirty_mult)
|
|||||||
|
|
||||||
test_skip_if(opt_purge != purge_mode_ratio);
|
test_skip_if(opt_purge != purge_mode_ratio);
|
||||||
|
|
||||||
assert_d_eq(mallctl("arena.0.lg_dirty_mult", &orig_lg_dirty_mult, &sz,
|
assert_d_eq(mallctl("arena.0.lg_dirty_mult",
|
||||||
NULL, 0), 0, "Unexpected mallctl() failure");
|
(void *)&orig_lg_dirty_mult, &sz, NULL, 0), 0,
|
||||||
|
"Unexpected mallctl() failure");
|
||||||
|
|
||||||
lg_dirty_mult = -2;
|
lg_dirty_mult = -2;
|
||||||
assert_d_eq(mallctl("arena.0.lg_dirty_mult", NULL, NULL,
|
assert_d_eq(mallctl("arena.0.lg_dirty_mult", NULL, NULL,
|
||||||
&lg_dirty_mult, sizeof(ssize_t)), EFAULT,
|
(void *)&lg_dirty_mult, sizeof(ssize_t)), EFAULT,
|
||||||
"Unexpected mallctl() success");
|
"Unexpected mallctl() success");
|
||||||
|
|
||||||
lg_dirty_mult = (sizeof(size_t) << 3);
|
lg_dirty_mult = (sizeof(size_t) << 3);
|
||||||
assert_d_eq(mallctl("arena.0.lg_dirty_mult", NULL, NULL,
|
assert_d_eq(mallctl("arena.0.lg_dirty_mult", NULL, NULL,
|
||||||
&lg_dirty_mult, sizeof(ssize_t)), EFAULT,
|
(void *)&lg_dirty_mult, sizeof(ssize_t)), EFAULT,
|
||||||
"Unexpected mallctl() success");
|
"Unexpected mallctl() success");
|
||||||
|
|
||||||
for (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1;
|
for (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1;
|
||||||
@@ -377,9 +386,9 @@ TEST_BEGIN(test_arena_i_lg_dirty_mult)
|
|||||||
= lg_dirty_mult, lg_dirty_mult++) {
|
= lg_dirty_mult, lg_dirty_mult++) {
|
||||||
ssize_t old_lg_dirty_mult;
|
ssize_t old_lg_dirty_mult;
|
||||||
|
|
||||||
assert_d_eq(mallctl("arena.0.lg_dirty_mult", &old_lg_dirty_mult,
|
assert_d_eq(mallctl("arena.0.lg_dirty_mult",
|
||||||
&sz, &lg_dirty_mult, sizeof(ssize_t)), 0,
|
(void *)&old_lg_dirty_mult, &sz, (void *)&lg_dirty_mult,
|
||||||
"Unexpected mallctl() failure");
|
sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
|
||||||
assert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult,
|
assert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult,
|
||||||
"Unexpected old arena.0.lg_dirty_mult");
|
"Unexpected old arena.0.lg_dirty_mult");
|
||||||
}
|
}
|
||||||
@@ -393,25 +402,25 @@ TEST_BEGIN(test_arena_i_decay_time)
|
|||||||
|
|
||||||
test_skip_if(opt_purge != purge_mode_decay);
|
test_skip_if(opt_purge != purge_mode_decay);
|
||||||
|
|
||||||
assert_d_eq(mallctl("arena.0.decay_time", &orig_decay_time, &sz,
|
assert_d_eq(mallctl("arena.0.decay_time", (void *)&orig_decay_time, &sz,
|
||||||
NULL, 0), 0, "Unexpected mallctl() failure");
|
NULL, 0), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
decay_time = -2;
|
decay_time = -2;
|
||||||
assert_d_eq(mallctl("arena.0.decay_time", NULL, NULL,
|
assert_d_eq(mallctl("arena.0.decay_time", NULL, NULL,
|
||||||
&decay_time, sizeof(ssize_t)), EFAULT,
|
(void *)&decay_time, sizeof(ssize_t)), EFAULT,
|
||||||
"Unexpected mallctl() success");
|
"Unexpected mallctl() success");
|
||||||
|
|
||||||
decay_time = 0x7fffffff;
|
decay_time = 0x7fffffff;
|
||||||
assert_d_eq(mallctl("arena.0.decay_time", NULL, NULL,
|
assert_d_eq(mallctl("arena.0.decay_time", NULL, NULL,
|
||||||
&decay_time, sizeof(ssize_t)), 0,
|
(void *)&decay_time, sizeof(ssize_t)), 0,
|
||||||
"Unexpected mallctl() failure");
|
"Unexpected mallctl() failure");
|
||||||
|
|
||||||
for (prev_decay_time = decay_time, decay_time = -1;
|
for (prev_decay_time = decay_time, decay_time = -1;
|
||||||
decay_time < 20; prev_decay_time = decay_time, decay_time++) {
|
decay_time < 20; prev_decay_time = decay_time, decay_time++) {
|
||||||
ssize_t old_decay_time;
|
ssize_t old_decay_time;
|
||||||
|
|
||||||
assert_d_eq(mallctl("arena.0.decay_time", &old_decay_time,
|
assert_d_eq(mallctl("arena.0.decay_time", (void *)&old_decay_time,
|
||||||
&sz, &decay_time, sizeof(ssize_t)), 0,
|
&sz, (void *)&decay_time, sizeof(ssize_t)), 0,
|
||||||
"Unexpected mallctl() failure");
|
"Unexpected mallctl() failure");
|
||||||
assert_zd_eq(old_decay_time, prev_decay_time,
|
assert_zd_eq(old_decay_time, prev_decay_time,
|
||||||
"Unexpected old arena.0.decay_time");
|
"Unexpected old arena.0.decay_time");
|
||||||
@@ -429,8 +438,8 @@ TEST_BEGIN(test_arena_i_purge)
|
|||||||
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
||||||
"Unexpected mallctl() failure");
|
"Unexpected mallctl() failure");
|
||||||
|
|
||||||
assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
assert_d_eq(mallctlnametomib("arena.0.purge", mib, &miblen), 0,
|
assert_d_eq(mallctlnametomib("arena.0.purge", mib, &miblen), 0,
|
||||||
"Unexpected mallctlnametomib() failure");
|
"Unexpected mallctlnametomib() failure");
|
||||||
mib[1] = narenas;
|
mib[1] = narenas;
|
||||||
@@ -449,8 +458,8 @@ TEST_BEGIN(test_arena_i_decay)
|
|||||||
assert_d_eq(mallctl("arena.0.decay", NULL, NULL, NULL, 0), 0,
|
assert_d_eq(mallctl("arena.0.decay", NULL, NULL, NULL, 0), 0,
|
||||||
"Unexpected mallctl() failure");
|
"Unexpected mallctl() failure");
|
||||||
|
|
||||||
assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
assert_d_eq(mallctlnametomib("arena.0.decay", mib, &miblen), 0,
|
assert_d_eq(mallctlnametomib("arena.0.decay", mib, &miblen), 0,
|
||||||
"Unexpected mallctlnametomib() failure");
|
"Unexpected mallctlnametomib() failure");
|
||||||
mib[1] = narenas;
|
mib[1] = narenas;
|
||||||
@@ -471,31 +480,35 @@ TEST_BEGIN(test_arena_i_dss)
|
|||||||
"Unexpected mallctlnametomib() error");
|
"Unexpected mallctlnametomib() error");
|
||||||
|
|
||||||
dss_prec_new = "disabled";
|
dss_prec_new = "disabled";
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new,
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz,
|
||||||
sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure");
|
(void *)&dss_prec_new, sizeof(dss_prec_new)), 0,
|
||||||
|
"Unexpected mallctl() failure");
|
||||||
assert_str_ne(dss_prec_old, "primary",
|
assert_str_ne(dss_prec_old, "primary",
|
||||||
"Unexpected default for dss precedence");
|
"Unexpected default for dss precedence");
|
||||||
|
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old,
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_new, &sz,
|
||||||
sizeof(dss_prec_old)), 0, "Unexpected mallctl() failure");
|
(void *)&dss_prec_old, sizeof(dss_prec_old)), 0,
|
||||||
|
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0,
|
|
||||||
"Unexpected mallctl() failure");
|
"Unexpected mallctl() failure");
|
||||||
|
|
||||||
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz, NULL,
|
||||||
|
0), 0, "Unexpected mallctl() failure");
|
||||||
assert_str_ne(dss_prec_old, "primary",
|
assert_str_ne(dss_prec_old, "primary",
|
||||||
"Unexpected value for dss precedence");
|
"Unexpected value for dss precedence");
|
||||||
|
|
||||||
mib[1] = narenas_total_get();
|
mib[1] = narenas_total_get();
|
||||||
dss_prec_new = "disabled";
|
dss_prec_new = "disabled";
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new,
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz,
|
||||||
sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure");
|
(void *)&dss_prec_new, sizeof(dss_prec_new)), 0,
|
||||||
|
"Unexpected mallctl() failure");
|
||||||
assert_str_ne(dss_prec_old, "primary",
|
assert_str_ne(dss_prec_old, "primary",
|
||||||
"Unexpected default for dss precedence");
|
"Unexpected default for dss precedence");
|
||||||
|
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old,
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_new, &sz,
|
||||||
sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure");
|
(void *)&dss_prec_old, sizeof(dss_prec_new)), 0,
|
||||||
|
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0,
|
|
||||||
"Unexpected mallctl() failure");
|
"Unexpected mallctl() failure");
|
||||||
|
|
||||||
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz, NULL,
|
||||||
|
0), 0, "Unexpected mallctl() failure");
|
||||||
assert_str_ne(dss_prec_old, "primary",
|
assert_str_ne(dss_prec_old, "primary",
|
||||||
"Unexpected value for dss precedence");
|
"Unexpected value for dss precedence");
|
||||||
}
|
}
|
||||||
@@ -506,14 +519,14 @@ TEST_BEGIN(test_arenas_initialized)
|
|||||||
unsigned narenas;
|
unsigned narenas;
|
||||||
size_t sz = sizeof(narenas);
|
size_t sz = sizeof(narenas);
|
||||||
|
|
||||||
assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
{
|
{
|
||||||
VARIABLE_ARRAY(bool, initialized, narenas);
|
VARIABLE_ARRAY(bool, initialized, narenas);
|
||||||
|
|
||||||
sz = narenas * sizeof(bool);
|
sz = narenas * sizeof(bool);
|
||||||
assert_d_eq(mallctl("arenas.initialized", initialized, &sz,
|
assert_d_eq(mallctl("arenas.initialized", (void *)initialized,
|
||||||
NULL, 0), 0, "Unexpected mallctl() failure");
|
&sz, NULL, 0), 0, "Unexpected mallctl() failure");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
@@ -525,17 +538,17 @@ TEST_BEGIN(test_arenas_lg_dirty_mult)
|
|||||||
|
|
||||||
test_skip_if(opt_purge != purge_mode_ratio);
|
test_skip_if(opt_purge != purge_mode_ratio);
|
||||||
|
|
||||||
assert_d_eq(mallctl("arenas.lg_dirty_mult", &orig_lg_dirty_mult, &sz,
|
assert_d_eq(mallctl("arenas.lg_dirty_mult", (void *)&orig_lg_dirty_mult,
|
||||||
NULL, 0), 0, "Unexpected mallctl() failure");
|
&sz, NULL, 0), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
lg_dirty_mult = -2;
|
lg_dirty_mult = -2;
|
||||||
assert_d_eq(mallctl("arenas.lg_dirty_mult", NULL, NULL,
|
assert_d_eq(mallctl("arenas.lg_dirty_mult", NULL, NULL,
|
||||||
&lg_dirty_mult, sizeof(ssize_t)), EFAULT,
|
(void *)&lg_dirty_mult, sizeof(ssize_t)), EFAULT,
|
||||||
"Unexpected mallctl() success");
|
"Unexpected mallctl() success");
|
||||||
|
|
||||||
lg_dirty_mult = (sizeof(size_t) << 3);
|
lg_dirty_mult = (sizeof(size_t) << 3);
|
||||||
assert_d_eq(mallctl("arenas.lg_dirty_mult", NULL, NULL,
|
assert_d_eq(mallctl("arenas.lg_dirty_mult", NULL, NULL,
|
||||||
&lg_dirty_mult, sizeof(ssize_t)), EFAULT,
|
(void *)&lg_dirty_mult, sizeof(ssize_t)), EFAULT,
|
||||||
"Unexpected mallctl() success");
|
"Unexpected mallctl() success");
|
||||||
|
|
||||||
for (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1;
|
for (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1;
|
||||||
@@ -543,9 +556,9 @@ TEST_BEGIN(test_arenas_lg_dirty_mult)
|
|||||||
lg_dirty_mult, lg_dirty_mult++) {
|
lg_dirty_mult, lg_dirty_mult++) {
|
||||||
ssize_t old_lg_dirty_mult;
|
ssize_t old_lg_dirty_mult;
|
||||||
|
|
||||||
assert_d_eq(mallctl("arenas.lg_dirty_mult", &old_lg_dirty_mult,
|
assert_d_eq(mallctl("arenas.lg_dirty_mult",
|
||||||
&sz, &lg_dirty_mult, sizeof(ssize_t)), 0,
|
(void *)&old_lg_dirty_mult, &sz, (void *)&lg_dirty_mult,
|
||||||
"Unexpected mallctl() failure");
|
sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
|
||||||
assert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult,
|
assert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult,
|
||||||
"Unexpected old arenas.lg_dirty_mult");
|
"Unexpected old arenas.lg_dirty_mult");
|
||||||
}
|
}
|
||||||
@@ -559,26 +572,26 @@ TEST_BEGIN(test_arenas_decay_time)
|
|||||||
|
|
||||||
test_skip_if(opt_purge != purge_mode_decay);
|
test_skip_if(opt_purge != purge_mode_decay);
|
||||||
|
|
||||||
assert_d_eq(mallctl("arenas.decay_time", &orig_decay_time, &sz,
|
assert_d_eq(mallctl("arenas.decay_time", (void *)&orig_decay_time, &sz,
|
||||||
NULL, 0), 0, "Unexpected mallctl() failure");
|
NULL, 0), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
decay_time = -2;
|
decay_time = -2;
|
||||||
assert_d_eq(mallctl("arenas.decay_time", NULL, NULL,
|
assert_d_eq(mallctl("arenas.decay_time", NULL, NULL,
|
||||||
&decay_time, sizeof(ssize_t)), EFAULT,
|
(void *)&decay_time, sizeof(ssize_t)), EFAULT,
|
||||||
"Unexpected mallctl() success");
|
"Unexpected mallctl() success");
|
||||||
|
|
||||||
decay_time = 0x7fffffff;
|
decay_time = 0x7fffffff;
|
||||||
assert_d_eq(mallctl("arenas.decay_time", NULL, NULL,
|
assert_d_eq(mallctl("arenas.decay_time", NULL, NULL,
|
||||||
&decay_time, sizeof(ssize_t)), 0,
|
(void *)&decay_time, sizeof(ssize_t)), 0,
|
||||||
"Expected mallctl() failure");
|
"Expected mallctl() failure");
|
||||||
|
|
||||||
for (prev_decay_time = decay_time, decay_time = -1;
|
for (prev_decay_time = decay_time, decay_time = -1;
|
||||||
decay_time < 20; prev_decay_time = decay_time, decay_time++) {
|
decay_time < 20; prev_decay_time = decay_time, decay_time++) {
|
||||||
ssize_t old_decay_time;
|
ssize_t old_decay_time;
|
||||||
|
|
||||||
assert_d_eq(mallctl("arenas.decay_time", &old_decay_time,
|
assert_d_eq(mallctl("arenas.decay_time",
|
||||||
&sz, &decay_time, sizeof(ssize_t)), 0,
|
(void *)&old_decay_time, &sz, (void *)&decay_time,
|
||||||
"Unexpected mallctl() failure");
|
sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
|
||||||
assert_zd_eq(old_decay_time, prev_decay_time,
|
assert_zd_eq(old_decay_time, prev_decay_time,
|
||||||
"Unexpected old arenas.decay_time");
|
"Unexpected old arenas.decay_time");
|
||||||
}
|
}
|
||||||
@@ -591,8 +604,8 @@ TEST_BEGIN(test_arenas_constants)
|
|||||||
#define TEST_ARENAS_CONSTANT(t, name, expected) do { \
|
#define TEST_ARENAS_CONSTANT(t, name, expected) do { \
|
||||||
t name; \
|
t name; \
|
||||||
size_t sz = sizeof(t); \
|
size_t sz = sizeof(t); \
|
||||||
assert_d_eq(mallctl("arenas."#name, &name, &sz, NULL, 0), 0, \
|
assert_d_eq(mallctl("arenas."#name, (void *)&name, &sz, NULL, \
|
||||||
"Unexpected mallctl() failure"); \
|
0), 0, "Unexpected mallctl() failure"); \
|
||||||
assert_zu_eq(name, expected, "Incorrect "#name" size"); \
|
assert_zu_eq(name, expected, "Incorrect "#name" size"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -612,8 +625,8 @@ TEST_BEGIN(test_arenas_bin_constants)
|
|||||||
#define TEST_ARENAS_BIN_CONSTANT(t, name, expected) do { \
|
#define TEST_ARENAS_BIN_CONSTANT(t, name, expected) do { \
|
||||||
t name; \
|
t name; \
|
||||||
size_t sz = sizeof(t); \
|
size_t sz = sizeof(t); \
|
||||||
assert_d_eq(mallctl("arenas.bin.0."#name, &name, &sz, NULL, 0), \
|
assert_d_eq(mallctl("arenas.bin.0."#name, (void *)&name, &sz, \
|
||||||
0, "Unexpected mallctl() failure"); \
|
NULL, 0), 0, "Unexpected mallctl() failure"); \
|
||||||
assert_zu_eq(name, expected, "Incorrect "#name" size"); \
|
assert_zu_eq(name, expected, "Incorrect "#name" size"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -631,8 +644,8 @@ TEST_BEGIN(test_arenas_lrun_constants)
|
|||||||
#define TEST_ARENAS_LRUN_CONSTANT(t, name, expected) do { \
|
#define TEST_ARENAS_LRUN_CONSTANT(t, name, expected) do { \
|
||||||
t name; \
|
t name; \
|
||||||
size_t sz = sizeof(t); \
|
size_t sz = sizeof(t); \
|
||||||
assert_d_eq(mallctl("arenas.lrun.0."#name, &name, &sz, NULL, \
|
assert_d_eq(mallctl("arenas.lrun.0."#name, (void *)&name, &sz, \
|
||||||
0), 0, "Unexpected mallctl() failure"); \
|
NULL, 0), 0, "Unexpected mallctl() failure"); \
|
||||||
assert_zu_eq(name, expected, "Incorrect "#name" size"); \
|
assert_zu_eq(name, expected, "Incorrect "#name" size"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -648,8 +661,8 @@ TEST_BEGIN(test_arenas_hchunk_constants)
|
|||||||
#define TEST_ARENAS_HCHUNK_CONSTANT(t, name, expected) do { \
|
#define TEST_ARENAS_HCHUNK_CONSTANT(t, name, expected) do { \
|
||||||
t name; \
|
t name; \
|
||||||
size_t sz = sizeof(t); \
|
size_t sz = sizeof(t); \
|
||||||
assert_d_eq(mallctl("arenas.hchunk.0."#name, &name, &sz, NULL, \
|
assert_d_eq(mallctl("arenas.hchunk.0."#name, (void *)&name, \
|
||||||
0), 0, "Unexpected mallctl() failure"); \
|
&sz, NULL, 0), 0, "Unexpected mallctl() failure"); \
|
||||||
assert_zu_eq(name, expected, "Incorrect "#name" size"); \
|
assert_zu_eq(name, expected, "Incorrect "#name" size"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -664,12 +677,12 @@ TEST_BEGIN(test_arenas_extend)
|
|||||||
unsigned narenas_before, arena, narenas_after;
|
unsigned narenas_before, arena, narenas_after;
|
||||||
size_t sz = sizeof(unsigned);
|
size_t sz = sizeof(unsigned);
|
||||||
|
|
||||||
assert_d_eq(mallctl("arenas.narenas", &narenas_before, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.narenas", (void *)&narenas_before, &sz,
|
||||||
"Unexpected mallctl() failure");
|
NULL, 0), 0, "Unexpected mallctl() failure");
|
||||||
assert_d_eq(mallctl("arenas.extend", &arena, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.extend", (void *)&arena, &sz, NULL, 0), 0,
|
||||||
"Unexpected mallctl() failure");
|
|
||||||
assert_d_eq(mallctl("arenas.narenas", &narenas_after, &sz, NULL, 0), 0,
|
|
||||||
"Unexpected mallctl() failure");
|
"Unexpected mallctl() failure");
|
||||||
|
assert_d_eq(mallctl("arenas.narenas", (void *)&narenas_after, &sz, NULL,
|
||||||
|
0), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
assert_u_eq(narenas_before+1, narenas_after,
|
assert_u_eq(narenas_before+1, narenas_after,
|
||||||
"Unexpected number of arenas before versus after extension");
|
"Unexpected number of arenas before versus after extension");
|
||||||
@@ -683,8 +696,8 @@ TEST_BEGIN(test_stats_arenas)
|
|||||||
#define TEST_STATS_ARENAS(t, name) do { \
|
#define TEST_STATS_ARENAS(t, name) do { \
|
||||||
t name; \
|
t name; \
|
||||||
size_t sz = sizeof(t); \
|
size_t sz = sizeof(t); \
|
||||||
assert_d_eq(mallctl("stats.arenas.0."#name, &name, &sz, NULL, \
|
assert_d_eq(mallctl("stats.arenas.0."#name, (void *)&name, &sz, \
|
||||||
0), 0, "Unexpected mallctl() failure"); \
|
NULL, 0), 0, "Unexpected mallctl() failure"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
TEST_STATS_ARENAS(unsigned, nthreads);
|
TEST_STATS_ARENAS(unsigned, nthreads);
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
|
#ifdef __PGI
|
||||||
|
#undef INFINITY
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef INFINITY
|
#ifndef INFINITY
|
||||||
#define INFINITY (DBL_MAX + DBL_MAX)
|
#define INFINITY (DBL_MAX + DBL_MAX)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -176,6 +176,13 @@ TEST_BEGIN(test_nstime_divide)
|
|||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_nstime_monotonic)
|
||||||
|
{
|
||||||
|
|
||||||
|
nstime_monotonic();
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
TEST_BEGIN(test_nstime_update)
|
TEST_BEGIN(test_nstime_update)
|
||||||
{
|
{
|
||||||
nstime_t nst;
|
nstime_t nst;
|
||||||
@@ -198,7 +205,6 @@ TEST_BEGIN(test_nstime_update)
|
|||||||
assert_d_eq(nstime_compare(&nst, &nst0), 0,
|
assert_d_eq(nstime_compare(&nst, &nst0), 0,
|
||||||
"Time should not have been modified");
|
"Time should not have been modified");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
@@ -216,5 +222,6 @@ main(void)
|
|||||||
test_nstime_imultiply,
|
test_nstime_imultiply,
|
||||||
test_nstime_idivide,
|
test_nstime_idivide,
|
||||||
test_nstime_divide,
|
test_nstime_divide,
|
||||||
|
test_nstime_monotonic,
|
||||||
test_nstime_update));
|
test_nstime_update));
|
||||||
}
|
}
|
||||||
|
|||||||
206
test/unit/pack.c
Normal file
206
test/unit/pack.c
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
|
const char *malloc_conf =
|
||||||
|
/* Use smallest possible chunk size. */
|
||||||
|
"lg_chunk:0"
|
||||||
|
/* Immediately purge to minimize fragmentation. */
|
||||||
|
",lg_dirty_mult:-1"
|
||||||
|
",decay_time:-1"
|
||||||
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size class that is a divisor of the page size, ideally 4+ regions per run.
|
||||||
|
*/
|
||||||
|
#if LG_PAGE <= 14
|
||||||
|
#define SZ (ZU(1) << (LG_PAGE - 2))
|
||||||
|
#else
|
||||||
|
#define SZ 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of chunks to consume at high water mark. Should be at least 2 so that
|
||||||
|
* if mmap()ed memory grows downward, downward growth of mmap()ed memory is
|
||||||
|
* tested.
|
||||||
|
*/
|
||||||
|
#define NCHUNKS 8
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
binind_compute(void)
|
||||||
|
{
|
||||||
|
size_t sz;
|
||||||
|
unsigned nbins, i;
|
||||||
|
|
||||||
|
sz = sizeof(nbins);
|
||||||
|
assert_d_eq(mallctl("arenas.nbins", (void *)&nbins, &sz, NULL, 0), 0,
|
||||||
|
"Unexpected mallctl failure");
|
||||||
|
|
||||||
|
for (i = 0; i < nbins; i++) {
|
||||||
|
size_t mib[4];
|
||||||
|
size_t miblen = sizeof(mib)/sizeof(size_t);
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
assert_d_eq(mallctlnametomib("arenas.bin.0.size", mib,
|
||||||
|
&miblen), 0, "Unexpected mallctlnametomb failure");
|
||||||
|
mib[2] = (size_t)i;
|
||||||
|
|
||||||
|
sz = sizeof(size);
|
||||||
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&size, &sz, NULL,
|
||||||
|
0), 0, "Unexpected mallctlbymib failure");
|
||||||
|
if (size == SZ)
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_fail("Unable to compute nregs_per_run");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
nregs_per_run_compute(void)
|
||||||
|
{
|
||||||
|
uint32_t nregs;
|
||||||
|
size_t sz;
|
||||||
|
unsigned binind = binind_compute();
|
||||||
|
size_t mib[4];
|
||||||
|
size_t miblen = sizeof(mib)/sizeof(size_t);
|
||||||
|
|
||||||
|
assert_d_eq(mallctlnametomib("arenas.bin.0.nregs", mib, &miblen), 0,
|
||||||
|
"Unexpected mallctlnametomb failure");
|
||||||
|
mib[2] = (size_t)binind;
|
||||||
|
sz = sizeof(nregs);
|
||||||
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&nregs, &sz, NULL,
|
||||||
|
0), 0, "Unexpected mallctlbymib failure");
|
||||||
|
return (nregs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
npages_per_run_compute(void)
|
||||||
|
{
|
||||||
|
size_t sz;
|
||||||
|
unsigned binind = binind_compute();
|
||||||
|
size_t mib[4];
|
||||||
|
size_t miblen = sizeof(mib)/sizeof(size_t);
|
||||||
|
size_t run_size;
|
||||||
|
|
||||||
|
assert_d_eq(mallctlnametomib("arenas.bin.0.run_size", mib, &miblen), 0,
|
||||||
|
"Unexpected mallctlnametomb failure");
|
||||||
|
mib[2] = (size_t)binind;
|
||||||
|
sz = sizeof(run_size);
|
||||||
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&run_size, &sz, NULL,
|
||||||
|
0), 0, "Unexpected mallctlbymib failure");
|
||||||
|
return (run_size >> LG_PAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
npages_per_chunk_compute(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return ((chunksize >> LG_PAGE) - map_bias);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
nruns_per_chunk_compute(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (npages_per_chunk_compute() / npages_per_run_compute());
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
arenas_extend_mallctl(void)
|
||||||
|
{
|
||||||
|
unsigned arena_ind;
|
||||||
|
size_t sz;
|
||||||
|
|
||||||
|
sz = sizeof(arena_ind);
|
||||||
|
assert_d_eq(mallctl("arenas.extend", (void *)&arena_ind, &sz, NULL, 0),
|
||||||
|
0, "Error in arenas.extend");
|
||||||
|
|
||||||
|
return (arena_ind);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
arena_reset_mallctl(unsigned arena_ind)
|
||||||
|
{
|
||||||
|
size_t mib[3];
|
||||||
|
size_t miblen = sizeof(mib)/sizeof(size_t);
|
||||||
|
|
||||||
|
assert_d_eq(mallctlnametomib("arena.0.reset", mib, &miblen), 0,
|
||||||
|
"Unexpected mallctlnametomib() failure");
|
||||||
|
mib[1] = (size_t)arena_ind;
|
||||||
|
assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
|
||||||
|
"Unexpected mallctlbymib() failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_BEGIN(test_pack)
|
||||||
|
{
|
||||||
|
unsigned arena_ind = arenas_extend_mallctl();
|
||||||
|
size_t nregs_per_run = nregs_per_run_compute();
|
||||||
|
size_t nruns_per_chunk = nruns_per_chunk_compute();
|
||||||
|
size_t nruns = nruns_per_chunk * NCHUNKS;
|
||||||
|
size_t nregs = nregs_per_run * nruns;
|
||||||
|
VARIABLE_ARRAY(void *, ptrs, nregs);
|
||||||
|
size_t i, j, offset;
|
||||||
|
|
||||||
|
/* Fill matrix. */
|
||||||
|
for (i = offset = 0; i < nruns; i++) {
|
||||||
|
for (j = 0; j < nregs_per_run; j++) {
|
||||||
|
void *p = mallocx(SZ, MALLOCX_ARENA(arena_ind) |
|
||||||
|
MALLOCX_TCACHE_NONE);
|
||||||
|
assert_ptr_not_null(p,
|
||||||
|
"Unexpected mallocx(%zu, MALLOCX_ARENA(%u) |"
|
||||||
|
" MALLOCX_TCACHE_NONE) failure, run=%zu, reg=%zu",
|
||||||
|
SZ, arena_ind, i, j);
|
||||||
|
ptrs[(i * nregs_per_run) + j] = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free all but one region of each run, but rotate which region is
|
||||||
|
* preserved, so that subsequent allocations exercise the within-run
|
||||||
|
* layout policy.
|
||||||
|
*/
|
||||||
|
offset = 0;
|
||||||
|
for (i = offset = 0;
|
||||||
|
i < nruns;
|
||||||
|
i++, offset = (offset + 1) % nregs_per_run) {
|
||||||
|
for (j = 0; j < nregs_per_run; j++) {
|
||||||
|
void *p = ptrs[(i * nregs_per_run) + j];
|
||||||
|
if (offset == j)
|
||||||
|
continue;
|
||||||
|
dallocx(p, MALLOCX_ARENA(arena_ind) |
|
||||||
|
MALLOCX_TCACHE_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Logically refill matrix, skipping preserved regions and verifying
|
||||||
|
* that the matrix is unmodified.
|
||||||
|
*/
|
||||||
|
offset = 0;
|
||||||
|
for (i = offset = 0;
|
||||||
|
i < nruns;
|
||||||
|
i++, offset = (offset + 1) % nregs_per_run) {
|
||||||
|
for (j = 0; j < nregs_per_run; j++) {
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if (offset == j)
|
||||||
|
continue;
|
||||||
|
p = mallocx(SZ, MALLOCX_ARENA(arena_ind) |
|
||||||
|
MALLOCX_TCACHE_NONE);
|
||||||
|
assert_ptr_eq(p, ptrs[(i * nregs_per_run) + j],
|
||||||
|
"Unexpected refill discrepancy, run=%zu, reg=%zu\n",
|
||||||
|
i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up. */
|
||||||
|
arena_reset_mallctl(arena_ind);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (test(
|
||||||
|
test_pack));
|
||||||
|
}
|
||||||
27
test/unit/pages.c
Normal file
27
test/unit/pages.c
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
|
TEST_BEGIN(test_pages_huge)
|
||||||
|
{
|
||||||
|
bool commit;
|
||||||
|
void *pages;
|
||||||
|
|
||||||
|
commit = true;
|
||||||
|
pages = pages_map(NULL, PAGE, &commit);
|
||||||
|
assert_ptr_not_null(pages, "Unexpected pages_map() error");
|
||||||
|
|
||||||
|
assert_false(pages_huge(pages, PAGE),
|
||||||
|
"Unexpected pages_huge() result");
|
||||||
|
assert_false(pages_nohuge(pages, PAGE),
|
||||||
|
"Unexpected pages_nohuge() result");
|
||||||
|
|
||||||
|
pages_unmap(pages, PAGE);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (test(
|
||||||
|
test_pages_huge));
|
||||||
|
}
|
||||||
219
test/unit/prng.c
219
test/unit/prng.c
@@ -1,33 +1,71 @@
|
|||||||
#include "test/jemalloc_test.h"
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
TEST_BEGIN(test_prng_lg_range)
|
static void
|
||||||
|
test_prng_lg_range_u32(bool atomic)
|
||||||
|
{
|
||||||
|
uint32_t sa, sb, ra, rb;
|
||||||
|
unsigned lg_range;
|
||||||
|
|
||||||
|
sa = 42;
|
||||||
|
ra = prng_lg_range_u32(&sa, 32, atomic);
|
||||||
|
sa = 42;
|
||||||
|
rb = prng_lg_range_u32(&sa, 32, atomic);
|
||||||
|
assert_u32_eq(ra, rb,
|
||||||
|
"Repeated generation should produce repeated results");
|
||||||
|
|
||||||
|
sb = 42;
|
||||||
|
rb = prng_lg_range_u32(&sb, 32, atomic);
|
||||||
|
assert_u32_eq(ra, rb,
|
||||||
|
"Equivalent generation should produce equivalent results");
|
||||||
|
|
||||||
|
sa = 42;
|
||||||
|
ra = prng_lg_range_u32(&sa, 32, atomic);
|
||||||
|
rb = prng_lg_range_u32(&sa, 32, atomic);
|
||||||
|
assert_u32_ne(ra, rb,
|
||||||
|
"Full-width results must not immediately repeat");
|
||||||
|
|
||||||
|
sa = 42;
|
||||||
|
ra = prng_lg_range_u32(&sa, 32, atomic);
|
||||||
|
for (lg_range = 31; lg_range > 0; lg_range--) {
|
||||||
|
sb = 42;
|
||||||
|
rb = prng_lg_range_u32(&sb, lg_range, atomic);
|
||||||
|
assert_u32_eq((rb & (UINT32_C(0xffffffff) << lg_range)),
|
||||||
|
0, "High order bits should be 0, lg_range=%u", lg_range);
|
||||||
|
assert_u32_eq(rb, (ra >> (32 - lg_range)),
|
||||||
|
"Expected high order bits of full-width result, "
|
||||||
|
"lg_range=%u", lg_range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_prng_lg_range_u64(void)
|
||||||
{
|
{
|
||||||
uint64_t sa, sb, ra, rb;
|
uint64_t sa, sb, ra, rb;
|
||||||
unsigned lg_range;
|
unsigned lg_range;
|
||||||
|
|
||||||
sa = 42;
|
sa = 42;
|
||||||
ra = prng_lg_range(&sa, 64);
|
ra = prng_lg_range_u64(&sa, 64);
|
||||||
sa = 42;
|
sa = 42;
|
||||||
rb = prng_lg_range(&sa, 64);
|
rb = prng_lg_range_u64(&sa, 64);
|
||||||
assert_u64_eq(ra, rb,
|
assert_u64_eq(ra, rb,
|
||||||
"Repeated generation should produce repeated results");
|
"Repeated generation should produce repeated results");
|
||||||
|
|
||||||
sb = 42;
|
sb = 42;
|
||||||
rb = prng_lg_range(&sb, 64);
|
rb = prng_lg_range_u64(&sb, 64);
|
||||||
assert_u64_eq(ra, rb,
|
assert_u64_eq(ra, rb,
|
||||||
"Equivalent generation should produce equivalent results");
|
"Equivalent generation should produce equivalent results");
|
||||||
|
|
||||||
sa = 42;
|
sa = 42;
|
||||||
ra = prng_lg_range(&sa, 64);
|
ra = prng_lg_range_u64(&sa, 64);
|
||||||
rb = prng_lg_range(&sa, 64);
|
rb = prng_lg_range_u64(&sa, 64);
|
||||||
assert_u64_ne(ra, rb,
|
assert_u64_ne(ra, rb,
|
||||||
"Full-width results must not immediately repeat");
|
"Full-width results must not immediately repeat");
|
||||||
|
|
||||||
sa = 42;
|
sa = 42;
|
||||||
ra = prng_lg_range(&sa, 64);
|
ra = prng_lg_range_u64(&sa, 64);
|
||||||
for (lg_range = 63; lg_range > 0; lg_range--) {
|
for (lg_range = 63; lg_range > 0; lg_range--) {
|
||||||
sb = 42;
|
sb = 42;
|
||||||
rb = prng_lg_range(&sb, lg_range);
|
rb = prng_lg_range_u64(&sb, lg_range);
|
||||||
assert_u64_eq((rb & (UINT64_C(0xffffffffffffffff) << lg_range)),
|
assert_u64_eq((rb & (UINT64_C(0xffffffffffffffff) << lg_range)),
|
||||||
0, "High order bits should be 0, lg_range=%u", lg_range);
|
0, "High order bits should be 0, lg_range=%u", lg_range);
|
||||||
assert_u64_eq(rb, (ra >> (64 - lg_range)),
|
assert_u64_eq(rb, (ra >> (64 - lg_range)),
|
||||||
@@ -35,9 +73,103 @@ TEST_BEGIN(test_prng_lg_range)
|
|||||||
"lg_range=%u", lg_range);
|
"lg_range=%u", lg_range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_prng_lg_range_zu(bool atomic)
|
||||||
|
{
|
||||||
|
size_t sa, sb, ra, rb;
|
||||||
|
unsigned lg_range;
|
||||||
|
|
||||||
|
sa = 42;
|
||||||
|
ra = prng_lg_range_zu(&sa, ZU(1) << (3 + LG_SIZEOF_PTR), atomic);
|
||||||
|
sa = 42;
|
||||||
|
rb = prng_lg_range_zu(&sa, ZU(1) << (3 + LG_SIZEOF_PTR), atomic);
|
||||||
|
assert_zu_eq(ra, rb,
|
||||||
|
"Repeated generation should produce repeated results");
|
||||||
|
|
||||||
|
sb = 42;
|
||||||
|
rb = prng_lg_range_zu(&sb, ZU(1) << (3 + LG_SIZEOF_PTR), atomic);
|
||||||
|
assert_zu_eq(ra, rb,
|
||||||
|
"Equivalent generation should produce equivalent results");
|
||||||
|
|
||||||
|
sa = 42;
|
||||||
|
ra = prng_lg_range_zu(&sa, ZU(1) << (3 + LG_SIZEOF_PTR), atomic);
|
||||||
|
rb = prng_lg_range_zu(&sa, ZU(1) << (3 + LG_SIZEOF_PTR), atomic);
|
||||||
|
assert_zu_ne(ra, rb,
|
||||||
|
"Full-width results must not immediately repeat");
|
||||||
|
|
||||||
|
sa = 42;
|
||||||
|
ra = prng_lg_range_zu(&sa, ZU(1) << (3 + LG_SIZEOF_PTR), atomic);
|
||||||
|
for (lg_range = (ZU(1) << (3 + LG_SIZEOF_PTR)) - 1; lg_range > 0;
|
||||||
|
lg_range--) {
|
||||||
|
sb = 42;
|
||||||
|
rb = prng_lg_range_zu(&sb, lg_range, atomic);
|
||||||
|
assert_zu_eq((rb & (SIZE_T_MAX << lg_range)),
|
||||||
|
0, "High order bits should be 0, lg_range=%u", lg_range);
|
||||||
|
assert_zu_eq(rb, (ra >> ((ZU(1) << (3 + LG_SIZEOF_PTR)) -
|
||||||
|
lg_range)), "Expected high order bits of full-width "
|
||||||
|
"result, lg_range=%u", lg_range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_BEGIN(test_prng_lg_range_u32_nonatomic)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_prng_lg_range_u32(false);
|
||||||
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
TEST_BEGIN(test_prng_range)
|
TEST_BEGIN(test_prng_lg_range_u32_atomic)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_prng_lg_range_u32(true);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_prng_lg_range_u64_nonatomic)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_prng_lg_range_u64();
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_prng_lg_range_zu_nonatomic)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_prng_lg_range_zu(false);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_prng_lg_range_zu_atomic)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_prng_lg_range_zu(true);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_prng_range_u32(bool atomic)
|
||||||
|
{
|
||||||
|
uint32_t range;
|
||||||
|
#define MAX_RANGE 10000000
|
||||||
|
#define RANGE_STEP 97
|
||||||
|
#define NREPS 10
|
||||||
|
|
||||||
|
for (range = 2; range < MAX_RANGE; range += RANGE_STEP) {
|
||||||
|
uint32_t s;
|
||||||
|
unsigned rep;
|
||||||
|
|
||||||
|
s = range;
|
||||||
|
for (rep = 0; rep < NREPS; rep++) {
|
||||||
|
uint32_t r = prng_range_u32(&s, range, atomic);
|
||||||
|
|
||||||
|
assert_u32_lt(r, range, "Out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_prng_range_u64(void)
|
||||||
{
|
{
|
||||||
uint64_t range;
|
uint64_t range;
|
||||||
#define MAX_RANGE 10000000
|
#define MAX_RANGE 10000000
|
||||||
@@ -50,12 +182,67 @@ TEST_BEGIN(test_prng_range)
|
|||||||
|
|
||||||
s = range;
|
s = range;
|
||||||
for (rep = 0; rep < NREPS; rep++) {
|
for (rep = 0; rep < NREPS; rep++) {
|
||||||
uint64_t r = prng_range(&s, range);
|
uint64_t r = prng_range_u64(&s, range);
|
||||||
|
|
||||||
assert_u64_lt(r, range, "Out of range");
|
assert_u64_lt(r, range, "Out of range");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_prng_range_zu(bool atomic)
|
||||||
|
{
|
||||||
|
size_t range;
|
||||||
|
#define MAX_RANGE 10000000
|
||||||
|
#define RANGE_STEP 97
|
||||||
|
#define NREPS 10
|
||||||
|
|
||||||
|
for (range = 2; range < MAX_RANGE; range += RANGE_STEP) {
|
||||||
|
size_t s;
|
||||||
|
unsigned rep;
|
||||||
|
|
||||||
|
s = range;
|
||||||
|
for (rep = 0; rep < NREPS; rep++) {
|
||||||
|
size_t r = prng_range_zu(&s, range, atomic);
|
||||||
|
|
||||||
|
assert_zu_lt(r, range, "Out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_BEGIN(test_prng_range_u32_nonatomic)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_prng_range_u32(false);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_prng_range_u32_atomic)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_prng_range_u32(true);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_prng_range_u64_nonatomic)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_prng_range_u64();
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_prng_range_zu_nonatomic)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_prng_range_zu(false);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_prng_range_zu_atomic)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_prng_range_zu(true);
|
||||||
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -63,6 +250,14 @@ main(void)
|
|||||||
{
|
{
|
||||||
|
|
||||||
return (test(
|
return (test(
|
||||||
test_prng_lg_range,
|
test_prng_lg_range_u32_nonatomic,
|
||||||
test_prng_range));
|
test_prng_lg_range_u32_atomic,
|
||||||
|
test_prng_lg_range_u64_nonatomic,
|
||||||
|
test_prng_lg_range_zu_nonatomic,
|
||||||
|
test_prng_lg_range_zu_atomic,
|
||||||
|
test_prng_range_u32_nonatomic,
|
||||||
|
test_prng_range_u32_atomic,
|
||||||
|
test_prng_range_u64_nonatomic,
|
||||||
|
test_prng_range_zu_nonatomic,
|
||||||
|
test_prng_range_zu_atomic));
|
||||||
}
|
}
|
||||||
|
|||||||
5
test/unit/prof_accum.c
Normal file → Executable file
5
test/unit/prof_accum.c
Normal file → Executable file
@@ -68,8 +68,9 @@ TEST_BEGIN(test_idump)
|
|||||||
test_skip_if(!config_prof);
|
test_skip_if(!config_prof);
|
||||||
|
|
||||||
active = true;
|
active = true;
|
||||||
assert_d_eq(mallctl("prof.active", NULL, NULL, &active, sizeof(active)),
|
assert_d_eq(mallctl("prof.active", NULL, NULL, (void *)&active,
|
||||||
0, "Unexpected mallctl failure while activating profiling");
|
sizeof(active)), 0,
|
||||||
|
"Unexpected mallctl failure while activating profiling");
|
||||||
|
|
||||||
prof_dump_open = prof_dump_open_intercept;
|
prof_dump_open = prof_dump_open_intercept;
|
||||||
|
|
||||||
|
|||||||
5
test/unit/prof_active.c
Normal file → Executable file
5
test/unit/prof_active.c
Normal file → Executable file
@@ -12,7 +12,7 @@ mallctl_bool_get(const char *name, bool expected, const char *func, int line)
|
|||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
sz = sizeof(old);
|
sz = sizeof(old);
|
||||||
assert_d_eq(mallctl(name, &old, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl(name, (void *)&old, &sz, NULL, 0), 0,
|
||||||
"%s():%d: Unexpected mallctl failure reading %s", func, line, name);
|
"%s():%d: Unexpected mallctl failure reading %s", func, line, name);
|
||||||
assert_b_eq(old, expected, "%s():%d: Unexpected %s value", func, line,
|
assert_b_eq(old, expected, "%s():%d: Unexpected %s value", func, line,
|
||||||
name);
|
name);
|
||||||
@@ -26,7 +26,8 @@ mallctl_bool_set(const char *name, bool old_expected, bool val_new,
|
|||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
sz = sizeof(old);
|
sz = sizeof(old);
|
||||||
assert_d_eq(mallctl(name, &old, &sz, &val_new, sizeof(val_new)), 0,
|
assert_d_eq(mallctl(name, (void *)&old, &sz, (void *)&val_new,
|
||||||
|
sizeof(val_new)), 0,
|
||||||
"%s():%d: Unexpected mallctl failure reading/writing %s", func,
|
"%s():%d: Unexpected mallctl failure reading/writing %s", func,
|
||||||
line, name);
|
line, name);
|
||||||
assert_b_eq(old, old_expected, "%s():%d: Unexpected %s value", func,
|
assert_b_eq(old, old_expected, "%s():%d: Unexpected %s value", func,
|
||||||
|
|||||||
13
test/unit/prof_gdump.c
Normal file → Executable file
13
test/unit/prof_gdump.c
Normal file → Executable file
@@ -28,8 +28,9 @@ TEST_BEGIN(test_gdump)
|
|||||||
test_skip_if(!config_prof);
|
test_skip_if(!config_prof);
|
||||||
|
|
||||||
active = true;
|
active = true;
|
||||||
assert_d_eq(mallctl("prof.active", NULL, NULL, &active, sizeof(active)),
|
assert_d_eq(mallctl("prof.active", NULL, NULL, (void *)&active,
|
||||||
0, "Unexpected mallctl failure while activating profiling");
|
sizeof(active)), 0,
|
||||||
|
"Unexpected mallctl failure while activating profiling");
|
||||||
|
|
||||||
prof_dump_open = prof_dump_open_intercept;
|
prof_dump_open = prof_dump_open_intercept;
|
||||||
|
|
||||||
@@ -45,8 +46,8 @@ TEST_BEGIN(test_gdump)
|
|||||||
|
|
||||||
gdump = false;
|
gdump = false;
|
||||||
sz = sizeof(gdump_old);
|
sz = sizeof(gdump_old);
|
||||||
assert_d_eq(mallctl("prof.gdump", &gdump_old, &sz, &gdump,
|
assert_d_eq(mallctl("prof.gdump", (void *)&gdump_old, &sz,
|
||||||
sizeof(gdump)), 0,
|
(void *)&gdump, sizeof(gdump)), 0,
|
||||||
"Unexpected mallctl failure while disabling prof.gdump");
|
"Unexpected mallctl failure while disabling prof.gdump");
|
||||||
assert(gdump_old);
|
assert(gdump_old);
|
||||||
did_prof_dump_open = false;
|
did_prof_dump_open = false;
|
||||||
@@ -56,8 +57,8 @@ TEST_BEGIN(test_gdump)
|
|||||||
|
|
||||||
gdump = true;
|
gdump = true;
|
||||||
sz = sizeof(gdump_old);
|
sz = sizeof(gdump_old);
|
||||||
assert_d_eq(mallctl("prof.gdump", &gdump_old, &sz, &gdump,
|
assert_d_eq(mallctl("prof.gdump", (void *)&gdump_old, &sz,
|
||||||
sizeof(gdump)), 0,
|
(void *)&gdump, sizeof(gdump)), 0,
|
||||||
"Unexpected mallctl failure while enabling prof.gdump");
|
"Unexpected mallctl failure while enabling prof.gdump");
|
||||||
assert(!gdump_old);
|
assert(!gdump_old);
|
||||||
did_prof_dump_open = false;
|
did_prof_dump_open = false;
|
||||||
|
|||||||
5
test/unit/prof_idump.c
Normal file → Executable file
5
test/unit/prof_idump.c
Normal file → Executable file
@@ -29,8 +29,9 @@ TEST_BEGIN(test_idump)
|
|||||||
test_skip_if(!config_prof);
|
test_skip_if(!config_prof);
|
||||||
|
|
||||||
active = true;
|
active = true;
|
||||||
assert_d_eq(mallctl("prof.active", NULL, NULL, &active, sizeof(active)),
|
assert_d_eq(mallctl("prof.active", NULL, NULL, (void *)&active,
|
||||||
0, "Unexpected mallctl failure while activating profiling");
|
sizeof(active)), 0,
|
||||||
|
"Unexpected mallctl failure while activating profiling");
|
||||||
|
|
||||||
prof_dump_open = prof_dump_open_intercept;
|
prof_dump_open = prof_dump_open_intercept;
|
||||||
|
|
||||||
|
|||||||
13
test/unit/prof_reset.c
Normal file → Executable file
13
test/unit/prof_reset.c
Normal file → Executable file
@@ -20,8 +20,8 @@ static void
|
|||||||
set_prof_active(bool active)
|
set_prof_active(bool active)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert_d_eq(mallctl("prof.active", NULL, NULL, &active, sizeof(active)),
|
assert_d_eq(mallctl("prof.active", NULL, NULL, (void *)&active,
|
||||||
0, "Unexpected mallctl failure");
|
sizeof(active)), 0, "Unexpected mallctl failure");
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
@@ -30,7 +30,8 @@ get_lg_prof_sample(void)
|
|||||||
size_t lg_prof_sample;
|
size_t lg_prof_sample;
|
||||||
size_t sz = sizeof(size_t);
|
size_t sz = sizeof(size_t);
|
||||||
|
|
||||||
assert_d_eq(mallctl("prof.lg_sample", &lg_prof_sample, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("prof.lg_sample", (void *)&lg_prof_sample, &sz,
|
||||||
|
NULL, 0), 0,
|
||||||
"Unexpected mallctl failure while reading profiling sample rate");
|
"Unexpected mallctl failure while reading profiling sample rate");
|
||||||
return (lg_prof_sample);
|
return (lg_prof_sample);
|
||||||
}
|
}
|
||||||
@@ -39,7 +40,7 @@ static void
|
|||||||
do_prof_reset(size_t lg_prof_sample)
|
do_prof_reset(size_t lg_prof_sample)
|
||||||
{
|
{
|
||||||
assert_d_eq(mallctl("prof.reset", NULL, NULL,
|
assert_d_eq(mallctl("prof.reset", NULL, NULL,
|
||||||
&lg_prof_sample, sizeof(size_t)), 0,
|
(void *)&lg_prof_sample, sizeof(size_t)), 0,
|
||||||
"Unexpected mallctl failure while resetting profile data");
|
"Unexpected mallctl failure while resetting profile data");
|
||||||
assert_zu_eq(lg_prof_sample, get_lg_prof_sample(),
|
assert_zu_eq(lg_prof_sample, get_lg_prof_sample(),
|
||||||
"Expected profile sample rate change");
|
"Expected profile sample rate change");
|
||||||
@@ -54,8 +55,8 @@ TEST_BEGIN(test_prof_reset_basic)
|
|||||||
test_skip_if(!config_prof);
|
test_skip_if(!config_prof);
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("opt.lg_prof_sample", &lg_prof_sample_orig, &sz,
|
assert_d_eq(mallctl("opt.lg_prof_sample", (void *)&lg_prof_sample_orig,
|
||||||
NULL, 0), 0,
|
&sz, NULL, 0), 0,
|
||||||
"Unexpected mallctl failure while reading profiling sample rate");
|
"Unexpected mallctl failure while reading profiling sample rate");
|
||||||
assert_zu_eq(lg_prof_sample_orig, 0,
|
assert_zu_eq(lg_prof_sample_orig, 0,
|
||||||
"Unexpected profiling sample rate");
|
"Unexpected profiling sample rate");
|
||||||
|
|||||||
22
test/unit/prof_thread_name.c
Normal file → Executable file
22
test/unit/prof_thread_name.c
Normal file → Executable file
@@ -12,8 +12,9 @@ mallctl_thread_name_get_impl(const char *thread_name_expected, const char *func,
|
|||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
sz = sizeof(thread_name_old);
|
sz = sizeof(thread_name_old);
|
||||||
assert_d_eq(mallctl("thread.prof.name", &thread_name_old, &sz, NULL, 0),
|
assert_d_eq(mallctl("thread.prof.name", (void *)&thread_name_old, &sz,
|
||||||
0, "%s():%d: Unexpected mallctl failure reading thread.prof.name",
|
NULL, 0), 0,
|
||||||
|
"%s():%d: Unexpected mallctl failure reading thread.prof.name",
|
||||||
func, line);
|
func, line);
|
||||||
assert_str_eq(thread_name_old, thread_name_expected,
|
assert_str_eq(thread_name_old, thread_name_expected,
|
||||||
"%s():%d: Unexpected thread.prof.name value", func, line);
|
"%s():%d: Unexpected thread.prof.name value", func, line);
|
||||||
@@ -26,8 +27,8 @@ mallctl_thread_name_set_impl(const char *thread_name, const char *func,
|
|||||||
int line)
|
int line)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert_d_eq(mallctl("thread.prof.name", NULL, NULL, &thread_name,
|
assert_d_eq(mallctl("thread.prof.name", NULL, NULL,
|
||||||
sizeof(thread_name)), 0,
|
(void *)&thread_name, sizeof(thread_name)), 0,
|
||||||
"%s():%d: Unexpected mallctl failure reading thread.prof.name",
|
"%s():%d: Unexpected mallctl failure reading thread.prof.name",
|
||||||
func, line);
|
func, line);
|
||||||
mallctl_thread_name_get_impl(thread_name, func, line);
|
mallctl_thread_name_get_impl(thread_name, func, line);
|
||||||
@@ -46,15 +47,15 @@ TEST_BEGIN(test_prof_thread_name_validation)
|
|||||||
|
|
||||||
/* NULL input shouldn't be allowed. */
|
/* NULL input shouldn't be allowed. */
|
||||||
thread_name = NULL;
|
thread_name = NULL;
|
||||||
assert_d_eq(mallctl("thread.prof.name", NULL, NULL, &thread_name,
|
assert_d_eq(mallctl("thread.prof.name", NULL, NULL,
|
||||||
sizeof(thread_name)), EFAULT,
|
(void *)&thread_name, sizeof(thread_name)), EFAULT,
|
||||||
"Unexpected mallctl result writing \"%s\" to thread.prof.name",
|
"Unexpected mallctl result writing \"%s\" to thread.prof.name",
|
||||||
thread_name);
|
thread_name);
|
||||||
|
|
||||||
/* '\n' shouldn't be allowed. */
|
/* '\n' shouldn't be allowed. */
|
||||||
thread_name = "hi\nthere";
|
thread_name = "hi\nthere";
|
||||||
assert_d_eq(mallctl("thread.prof.name", NULL, NULL, &thread_name,
|
assert_d_eq(mallctl("thread.prof.name", NULL, NULL,
|
||||||
sizeof(thread_name)), EFAULT,
|
(void *)&thread_name, sizeof(thread_name)), EFAULT,
|
||||||
"Unexpected mallctl result writing \"%s\" to thread.prof.name",
|
"Unexpected mallctl result writing \"%s\" to thread.prof.name",
|
||||||
thread_name);
|
thread_name);
|
||||||
|
|
||||||
@@ -64,8 +65,9 @@ TEST_BEGIN(test_prof_thread_name_validation)
|
|||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
sz = sizeof(thread_name_old);
|
sz = sizeof(thread_name_old);
|
||||||
assert_d_eq(mallctl("thread.prof.name", &thread_name_old, &sz,
|
assert_d_eq(mallctl("thread.prof.name",
|
||||||
&thread_name, sizeof(thread_name)), EPERM,
|
(void *)&thread_name_old, &sz, (void *)&thread_name,
|
||||||
|
sizeof(thread_name)), EPERM,
|
||||||
"Unexpected mallctl result writing \"%s\" to "
|
"Unexpected mallctl result writing \"%s\" to "
|
||||||
"thread.prof.name", thread_name);
|
"thread.prof.name", thread_name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ TEST_BEGIN(test_small_run_size)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("arenas.nbins", &nbins, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.nbins", (void *)&nbins, &sz, NULL, 0), 0,
|
||||||
"Unexpected mallctl failure");
|
"Unexpected mallctl failure");
|
||||||
|
|
||||||
assert_d_eq(mallctlnametomib("arenas.bin.0.run_size", mib, &miblen), 0,
|
assert_d_eq(mallctlnametomib("arenas.bin.0.run_size", mib, &miblen), 0,
|
||||||
@@ -21,8 +21,8 @@ TEST_BEGIN(test_small_run_size)
|
|||||||
for (i = 0; i < nbins; i++) {
|
for (i = 0; i < nbins; i++) {
|
||||||
mib[2] = i;
|
mib[2] = i;
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &run_size, &sz, NULL, 0),
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&run_size, &sz,
|
||||||
0, "Unexpected mallctlbymib failure");
|
NULL, 0), 0, "Unexpected mallctlbymib failure");
|
||||||
assert_zu_eq(run_size, run_quantize_floor(run_size),
|
assert_zu_eq(run_size, run_quantize_floor(run_size),
|
||||||
"Small run quantization should be a no-op (run_size=%zu)",
|
"Small run quantization should be a no-op (run_size=%zu)",
|
||||||
run_size);
|
run_size);
|
||||||
@@ -47,11 +47,11 @@ TEST_BEGIN(test_large_run_size)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
sz = sizeof(bool);
|
sz = sizeof(bool);
|
||||||
assert_d_eq(mallctl("config.cache_oblivious", &cache_oblivious, &sz,
|
assert_d_eq(mallctl("config.cache_oblivious", (void *)&cache_oblivious,
|
||||||
NULL, 0), 0, "Unexpected mallctl failure");
|
&sz, NULL, 0), 0, "Unexpected mallctl failure");
|
||||||
|
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("arenas.nlruns", &nlruns, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.nlruns", (void *)&nlruns, &sz, NULL, 0), 0,
|
||||||
"Unexpected mallctl failure");
|
"Unexpected mallctl failure");
|
||||||
|
|
||||||
assert_d_eq(mallctlnametomib("arenas.lrun.0.size", mib, &miblen), 0,
|
assert_d_eq(mallctlnametomib("arenas.lrun.0.size", mib, &miblen), 0,
|
||||||
@@ -61,8 +61,8 @@ TEST_BEGIN(test_large_run_size)
|
|||||||
|
|
||||||
mib[2] = i;
|
mib[2] = i;
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &lrun_size, &sz, NULL, 0),
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&lrun_size, &sz,
|
||||||
0, "Unexpected mallctlbymib failure");
|
NULL, 0), 0, "Unexpected mallctlbymib failure");
|
||||||
run_size = cache_oblivious ? lrun_size + PAGE : lrun_size;
|
run_size = cache_oblivious ? lrun_size + PAGE : lrun_size;
|
||||||
floor = run_quantize_floor(run_size);
|
floor = run_quantize_floor(run_size);
|
||||||
ceil = run_quantize_ceil(run_size);
|
ceil = run_quantize_ceil(run_size);
|
||||||
@@ -102,16 +102,16 @@ TEST_BEGIN(test_monotonic)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("arenas.nbins", &nbins, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.nbins", (void *)&nbins, &sz, NULL, 0), 0,
|
||||||
"Unexpected mallctl failure");
|
"Unexpected mallctl failure");
|
||||||
|
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("arenas.nlruns", &nlruns, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.nlruns", (void *)&nlruns, &sz, NULL, 0), 0,
|
||||||
"Unexpected mallctl failure");
|
"Unexpected mallctl failure");
|
||||||
|
|
||||||
floor_prev = 0;
|
floor_prev = 0;
|
||||||
ceil_prev = 0;
|
ceil_prev = 0;
|
||||||
for (i = 1; i < run_quantize_max >> LG_PAGE; i++) {
|
for (i = 1; i <= chunksize >> LG_PAGE; i++) {
|
||||||
size_t run_size, floor, ceil;
|
size_t run_size, floor, ceil;
|
||||||
|
|
||||||
run_size = i << LG_PAGE;
|
run_size = i << LG_PAGE;
|
||||||
|
|||||||
100
test/unit/size_classes.c
Normal file → Executable file
100
test/unit/size_classes.c
Normal file → Executable file
@@ -8,8 +8,8 @@ get_max_size_class(void)
|
|||||||
size_t sz, miblen, max_size_class;
|
size_t sz, miblen, max_size_class;
|
||||||
|
|
||||||
sz = sizeof(unsigned);
|
sz = sizeof(unsigned);
|
||||||
assert_d_eq(mallctl("arenas.nhchunks", &nhchunks, &sz, NULL, 0), 0,
|
assert_d_eq(mallctl("arenas.nhchunks", (void *)&nhchunks, &sz, NULL, 0),
|
||||||
"Unexpected mallctl() error");
|
0, "Unexpected mallctl() error");
|
||||||
|
|
||||||
miblen = sizeof(mib) / sizeof(size_t);
|
miblen = sizeof(mib) / sizeof(size_t);
|
||||||
assert_d_eq(mallctlnametomib("arenas.hchunk.0.size", mib, &miblen), 0,
|
assert_d_eq(mallctlnametomib("arenas.hchunk.0.size", mib, &miblen), 0,
|
||||||
@@ -17,8 +17,8 @@ get_max_size_class(void)
|
|||||||
mib[2] = nhchunks - 1;
|
mib[2] = nhchunks - 1;
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctlbymib(mib, miblen, &max_size_class, &sz, NULL, 0), 0,
|
assert_d_eq(mallctlbymib(mib, miblen, (void *)&max_size_class, &sz,
|
||||||
"Unexpected mallctlbymib() error");
|
NULL, 0), 0, "Unexpected mallctlbymib() error");
|
||||||
|
|
||||||
return (max_size_class);
|
return (max_size_class);
|
||||||
}
|
}
|
||||||
@@ -80,25 +80,96 @@ TEST_BEGIN(test_size_classes)
|
|||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_psize_classes)
|
||||||
|
{
|
||||||
|
size_t size_class, max_size_class;
|
||||||
|
pszind_t pind, max_pind;
|
||||||
|
|
||||||
|
max_size_class = get_max_size_class();
|
||||||
|
max_pind = psz2ind(max_size_class);
|
||||||
|
|
||||||
|
for (pind = 0, size_class = pind2sz(pind); pind < max_pind ||
|
||||||
|
size_class < max_size_class; pind++, size_class =
|
||||||
|
pind2sz(pind)) {
|
||||||
|
assert_true(pind < max_pind,
|
||||||
|
"Loop conditionals should be equivalent; pind=%u, "
|
||||||
|
"size_class=%zu (%#zx)", pind, size_class, size_class);
|
||||||
|
assert_true(size_class < max_size_class,
|
||||||
|
"Loop conditionals should be equivalent; pind=%u, "
|
||||||
|
"size_class=%zu (%#zx)", pind, size_class, size_class);
|
||||||
|
|
||||||
|
assert_u_eq(pind, psz2ind(size_class),
|
||||||
|
"psz2ind() does not reverse pind2sz(): pind=%u -->"
|
||||||
|
" size_class=%zu --> pind=%u --> size_class=%zu", pind,
|
||||||
|
size_class, psz2ind(size_class),
|
||||||
|
pind2sz(psz2ind(size_class)));
|
||||||
|
assert_zu_eq(size_class, pind2sz(psz2ind(size_class)),
|
||||||
|
"pind2sz() does not reverse psz2ind(): pind=%u -->"
|
||||||
|
" size_class=%zu --> pind=%u --> size_class=%zu", pind,
|
||||||
|
size_class, psz2ind(size_class),
|
||||||
|
pind2sz(psz2ind(size_class)));
|
||||||
|
|
||||||
|
assert_u_eq(pind+1, psz2ind(size_class+1),
|
||||||
|
"Next size_class does not round up properly");
|
||||||
|
|
||||||
|
assert_zu_eq(size_class, (pind > 0) ?
|
||||||
|
psz2u(pind2sz(pind-1)+1) : psz2u(1),
|
||||||
|
"psz2u() does not round up to size class");
|
||||||
|
assert_zu_eq(size_class, psz2u(size_class-1),
|
||||||
|
"psz2u() does not round up to size class");
|
||||||
|
assert_zu_eq(size_class, psz2u(size_class),
|
||||||
|
"psz2u() does not compute same size class");
|
||||||
|
assert_zu_eq(psz2u(size_class+1), pind2sz(pind+1),
|
||||||
|
"psz2u() does not round up to next size class");
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_u_eq(pind, psz2ind(pind2sz(pind)),
|
||||||
|
"psz2ind() does not reverse pind2sz()");
|
||||||
|
assert_zu_eq(max_size_class, pind2sz(psz2ind(max_size_class)),
|
||||||
|
"pind2sz() does not reverse psz2ind()");
|
||||||
|
|
||||||
|
assert_zu_eq(size_class, psz2u(pind2sz(pind-1)+1),
|
||||||
|
"psz2u() does not round up to size class");
|
||||||
|
assert_zu_eq(size_class, psz2u(size_class-1),
|
||||||
|
"psz2u() does not round up to size class");
|
||||||
|
assert_zu_eq(size_class, psz2u(size_class),
|
||||||
|
"psz2u() does not compute same size class");
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
TEST_BEGIN(test_overflow)
|
TEST_BEGIN(test_overflow)
|
||||||
{
|
{
|
||||||
size_t max_size_class;
|
size_t max_size_class;
|
||||||
|
|
||||||
max_size_class = get_max_size_class();
|
max_size_class = get_max_size_class();
|
||||||
|
|
||||||
assert_u_ge(size2index(max_size_class+1), NSIZES,
|
assert_u_eq(size2index(max_size_class+1), NSIZES,
|
||||||
"size2index() should return >= NSIZES on overflow");
|
"size2index() should return NSIZES on overflow");
|
||||||
assert_u_ge(size2index(ZU(PTRDIFF_MAX)+1), NSIZES,
|
assert_u_eq(size2index(ZU(PTRDIFF_MAX)+1), NSIZES,
|
||||||
"size2index() should return >= NSIZES on overflow");
|
"size2index() should return NSIZES on overflow");
|
||||||
assert_u_ge(size2index(SIZE_T_MAX), NSIZES,
|
assert_u_eq(size2index(SIZE_T_MAX), NSIZES,
|
||||||
"size2index() should return >= NSIZES on overflow");
|
"size2index() should return NSIZES on overflow");
|
||||||
|
|
||||||
assert_zu_gt(s2u(max_size_class+1), HUGE_MAXCLASS,
|
assert_zu_eq(s2u(max_size_class+1), 0,
|
||||||
"s2u() should return > HUGE_MAXCLASS for unsupported size");
|
"s2u() should return 0 for unsupported size");
|
||||||
assert_zu_gt(s2u(ZU(PTRDIFF_MAX)+1), HUGE_MAXCLASS,
|
assert_zu_eq(s2u(ZU(PTRDIFF_MAX)+1), 0,
|
||||||
"s2u() should return > HUGE_MAXCLASS for unsupported size");
|
"s2u() should return 0 for unsupported size");
|
||||||
assert_zu_eq(s2u(SIZE_T_MAX), 0,
|
assert_zu_eq(s2u(SIZE_T_MAX), 0,
|
||||||
"s2u() should return 0 on overflow");
|
"s2u() should return 0 on overflow");
|
||||||
|
|
||||||
|
assert_u_eq(psz2ind(max_size_class+1), NPSIZES,
|
||||||
|
"psz2ind() should return NPSIZES on overflow");
|
||||||
|
assert_u_eq(psz2ind(ZU(PTRDIFF_MAX)+1), NPSIZES,
|
||||||
|
"psz2ind() should return NPSIZES on overflow");
|
||||||
|
assert_u_eq(psz2ind(SIZE_T_MAX), NPSIZES,
|
||||||
|
"psz2ind() should return NPSIZES on overflow");
|
||||||
|
|
||||||
|
assert_zu_eq(psz2u(max_size_class+1), 0,
|
||||||
|
"psz2u() should return 0 for unsupported size");
|
||||||
|
assert_zu_eq(psz2u(ZU(PTRDIFF_MAX)+1), 0,
|
||||||
|
"psz2u() should return 0 for unsupported size");
|
||||||
|
assert_zu_eq(psz2u(SIZE_T_MAX), 0,
|
||||||
|
"psz2u() should return 0 on overflow");
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
@@ -108,5 +179,6 @@ main(void)
|
|||||||
|
|
||||||
return (test(
|
return (test(
|
||||||
test_size_classes,
|
test_size_classes,
|
||||||
|
test_psize_classes,
|
||||||
test_overflow));
|
test_overflow));
|
||||||
}
|
}
|
||||||
|
|||||||
223
test/unit/stats.c
Normal file → Executable file
223
test/unit/stats.c
Normal file → Executable file
@@ -7,18 +7,18 @@ TEST_BEGIN(test_stats_summary)
|
|||||||
int expected = config_stats ? 0 : ENOENT;
|
int expected = config_stats ? 0 : ENOENT;
|
||||||
|
|
||||||
sz = sizeof(cactive);
|
sz = sizeof(cactive);
|
||||||
assert_d_eq(mallctl("stats.cactive", &cactive, &sz, NULL, 0), expected,
|
assert_d_eq(mallctl("stats.cactive", (void *)&cactive, &sz, NULL, 0),
|
||||||
"Unexpected mallctl() result");
|
expected, "Unexpected mallctl() result");
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("stats.allocated", &allocated, &sz, NULL, 0),
|
assert_d_eq(mallctl("stats.allocated", (void *)&allocated, &sz, NULL,
|
||||||
|
0), expected, "Unexpected mallctl() result");
|
||||||
|
assert_d_eq(mallctl("stats.active", (void *)&active, &sz, NULL, 0),
|
||||||
expected, "Unexpected mallctl() result");
|
expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.active", &active, &sz, NULL, 0), expected,
|
assert_d_eq(mallctl("stats.resident", (void *)&resident, &sz, NULL, 0),
|
||||||
"Unexpected mallctl() result");
|
expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.resident", &resident, &sz, NULL, 0),
|
assert_d_eq(mallctl("stats.mapped", (void *)&mapped, &sz, NULL, 0),
|
||||||
expected, "Unexpected mallctl() result");
|
expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.mapped", &mapped, &sz, NULL, 0), expected,
|
|
||||||
"Unexpected mallctl() result");
|
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
assert_zu_le(active, *cactive,
|
assert_zu_le(active, *cactive,
|
||||||
@@ -45,19 +45,19 @@ TEST_BEGIN(test_stats_huge)
|
|||||||
p = mallocx(large_maxclass+1, 0);
|
p = mallocx(large_maxclass+1, 0);
|
||||||
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
||||||
|
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.huge.allocated", &allocated, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.huge.allocated", (void *)&allocated,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.huge.nmalloc", &nmalloc, &sz, NULL,
|
assert_d_eq(mallctl("stats.arenas.0.huge.nmalloc", (void *)&nmalloc,
|
||||||
0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.huge.ndalloc", &ndalloc, &sz, NULL,
|
assert_d_eq(mallctl("stats.arenas.0.huge.ndalloc", (void *)&ndalloc,
|
||||||
0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.huge.nrequests", &nrequests, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.huge.nrequests", (void *)&nrequests,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
assert_zu_gt(allocated, 0,
|
assert_zu_gt(allocated, 0,
|
||||||
@@ -83,8 +83,8 @@ TEST_BEGIN(test_stats_arenas_summary)
|
|||||||
uint64_t npurge, nmadvise, purged;
|
uint64_t npurge, nmadvise, purged;
|
||||||
|
|
||||||
arena = 0;
|
arena = 0;
|
||||||
assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
|
assert_d_eq(mallctl("thread.arena", NULL, NULL, (void *)&arena,
|
||||||
0, "Unexpected mallctl() failure");
|
sizeof(arena)), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
little = mallocx(SMALL_MAXCLASS, 0);
|
little = mallocx(SMALL_MAXCLASS, 0);
|
||||||
assert_ptr_not_null(little, "Unexpected mallocx() failure");
|
assert_ptr_not_null(little, "Unexpected mallocx() failure");
|
||||||
@@ -100,19 +100,19 @@ TEST_BEGIN(test_stats_arenas_summary)
|
|||||||
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
|
||||||
"Unexpected mallctl() failure");
|
"Unexpected mallctl() failure");
|
||||||
|
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.mapped", &mapped, &sz, NULL, 0),
|
assert_d_eq(mallctl("stats.arenas.0.mapped", (void *)&mapped, &sz, NULL,
|
||||||
expected, "Unexepected mallctl() result");
|
0), expected, "Unexepected mallctl() result");
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.npurge", &npurge, &sz, NULL, 0),
|
assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge, &sz, NULL,
|
||||||
expected, "Unexepected mallctl() result");
|
0), expected, "Unexepected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.nmadvise", &nmadvise, &sz, NULL, 0),
|
assert_d_eq(mallctl("stats.arenas.0.nmadvise", (void *)&nmadvise, &sz,
|
||||||
expected, "Unexepected mallctl() result");
|
NULL, 0), expected, "Unexepected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.purged", &purged, &sz, NULL, 0),
|
assert_d_eq(mallctl("stats.arenas.0.purged", (void *)&purged, &sz, NULL,
|
||||||
expected, "Unexepected mallctl() result");
|
0), expected, "Unexepected mallctl() result");
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
assert_u64_gt(npurge, 0,
|
assert_u64_gt(npurge, 0,
|
||||||
@@ -150,8 +150,8 @@ TEST_BEGIN(test_stats_arenas_small)
|
|||||||
no_lazy_lock(); /* Lazy locking would dodge tcache testing. */
|
no_lazy_lock(); /* Lazy locking would dodge tcache testing. */
|
||||||
|
|
||||||
arena = 0;
|
arena = 0;
|
||||||
assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
|
assert_d_eq(mallctl("thread.arena", NULL, NULL, (void *)&arena,
|
||||||
0, "Unexpected mallctl() failure");
|
sizeof(arena)), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
p = mallocx(SMALL_MAXCLASS, 0);
|
p = mallocx(SMALL_MAXCLASS, 0);
|
||||||
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
||||||
@@ -159,19 +159,21 @@ TEST_BEGIN(test_stats_arenas_small)
|
|||||||
assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
|
assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
|
||||||
config_tcache ? 0 : ENOENT, "Unexpected mallctl() result");
|
config_tcache ? 0 : ENOENT, "Unexpected mallctl() result");
|
||||||
|
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.small.allocated", &allocated, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.small.allocated",
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
(void *)&allocated, &sz, NULL, 0), expected,
|
||||||
|
"Unexpected mallctl() result");
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.small.nmalloc", &nmalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.small.nmalloc", (void *)&nmalloc,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.small.ndalloc", &ndalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.small.ndalloc", (void *)&ndalloc,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.small.nrequests", &nrequests, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.small.nrequests",
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
(void *)&nrequests, &sz, NULL, 0), expected,
|
||||||
|
"Unexpected mallctl() result");
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
assert_zu_gt(allocated, 0,
|
assert_zu_gt(allocated, 0,
|
||||||
@@ -197,25 +199,27 @@ TEST_BEGIN(test_stats_arenas_large)
|
|||||||
int expected = config_stats ? 0 : ENOENT;
|
int expected = config_stats ? 0 : ENOENT;
|
||||||
|
|
||||||
arena = 0;
|
arena = 0;
|
||||||
assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
|
assert_d_eq(mallctl("thread.arena", NULL, NULL, (void *)&arena,
|
||||||
0, "Unexpected mallctl() failure");
|
sizeof(arena)), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
p = mallocx(large_maxclass, 0);
|
p = mallocx(large_maxclass, 0);
|
||||||
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
||||||
|
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.large.allocated", &allocated, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.large.allocated",
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
(void *)&allocated, &sz, NULL, 0), expected,
|
||||||
|
"Unexpected mallctl() result");
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", &nmalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", (void *)&nmalloc,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", &ndalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", (void *)&ndalloc,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.large.nrequests", &nrequests, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.large.nrequests",
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
(void *)&nrequests, &sz, NULL, 0), expected,
|
||||||
|
"Unexpected mallctl() result");
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
assert_zu_gt(allocated, 0,
|
assert_zu_gt(allocated, 0,
|
||||||
@@ -241,23 +245,23 @@ TEST_BEGIN(test_stats_arenas_huge)
|
|||||||
int expected = config_stats ? 0 : ENOENT;
|
int expected = config_stats ? 0 : ENOENT;
|
||||||
|
|
||||||
arena = 0;
|
arena = 0;
|
||||||
assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
|
assert_d_eq(mallctl("thread.arena", NULL, NULL, (void *)&arena,
|
||||||
0, "Unexpected mallctl() failure");
|
sizeof(arena)), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
p = mallocx(chunksize, 0);
|
p = mallocx(chunksize, 0);
|
||||||
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
||||||
|
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.huge.allocated", &allocated, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.huge.allocated", (void *)&allocated,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.huge.nmalloc", &nmalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.huge.nmalloc", (void *)&nmalloc,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.huge.ndalloc", &ndalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.huge.ndalloc", (void *)&ndalloc,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
assert_zu_gt(allocated, 0,
|
assert_zu_gt(allocated, 0,
|
||||||
@@ -282,8 +286,8 @@ TEST_BEGIN(test_stats_arenas_bins)
|
|||||||
int expected = config_stats ? 0 : ENOENT;
|
int expected = config_stats ? 0 : ENOENT;
|
||||||
|
|
||||||
arena = 0;
|
arena = 0;
|
||||||
assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
|
assert_d_eq(mallctl("thread.arena", NULL, NULL, (void *)&arena,
|
||||||
0, "Unexpected mallctl() failure");
|
sizeof(arena)), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
p = mallocx(arena_bin_info[0].reg_size, 0);
|
p = mallocx(arena_bin_info[0].reg_size, 0);
|
||||||
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
||||||
@@ -291,35 +295,36 @@ TEST_BEGIN(test_stats_arenas_bins)
|
|||||||
assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
|
assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
|
||||||
config_tcache ? 0 : ENOENT, "Unexpected mallctl() result");
|
config_tcache ? 0 : ENOENT, "Unexpected mallctl() result");
|
||||||
|
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.nmalloc", &nmalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.bins.0.nmalloc", (void *)&nmalloc,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.ndalloc", &ndalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.bins.0.ndalloc", (void *)&ndalloc,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.nrequests", &nrequests, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.bins.0.nrequests",
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
(void *)&nrequests, &sz, NULL, 0), expected,
|
||||||
|
"Unexpected mallctl() result");
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.curregs", &curregs, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.bins.0.curregs", (void *)&curregs,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
|
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.nfills", &nfills, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.bins.0.nfills", (void *)&nfills,
|
||||||
NULL, 0), config_tcache ? expected : ENOENT,
|
&sz, NULL, 0), config_tcache ? expected : ENOENT,
|
||||||
"Unexpected mallctl() result");
|
"Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.nflushes", &nflushes, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.bins.0.nflushes", (void *)&nflushes,
|
||||||
NULL, 0), config_tcache ? expected : ENOENT,
|
&sz, NULL, 0), config_tcache ? expected : ENOENT,
|
||||||
"Unexpected mallctl() result");
|
"Unexpected mallctl() result");
|
||||||
|
|
||||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.nruns", &nruns, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.bins.0.nruns", (void *)&nruns, &sz,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
|
||||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.nreruns", &nreruns, &sz,
|
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
|
assert_d_eq(mallctl("stats.arenas.0.bins.0.nreruns", (void *)&nreruns,
|
||||||
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.bins.0.curruns", &curruns, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.bins.0.curruns", (void *)&curruns,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
assert_u64_gt(nmalloc, 0,
|
assert_u64_gt(nmalloc, 0,
|
||||||
@@ -355,25 +360,26 @@ TEST_BEGIN(test_stats_arenas_lruns)
|
|||||||
int expected = config_stats ? 0 : ENOENT;
|
int expected = config_stats ? 0 : ENOENT;
|
||||||
|
|
||||||
arena = 0;
|
arena = 0;
|
||||||
assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
|
assert_d_eq(mallctl("thread.arena", NULL, NULL, (void *)&arena,
|
||||||
0, "Unexpected mallctl() failure");
|
sizeof(arena)), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
p = mallocx(LARGE_MINCLASS, 0);
|
p = mallocx(LARGE_MINCLASS, 0);
|
||||||
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
||||||
|
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.lruns.0.nmalloc", &nmalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.lruns.0.nmalloc", (void *)&nmalloc,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.lruns.0.ndalloc", &ndalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.lruns.0.ndalloc", (void *)&ndalloc,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
assert_d_eq(mallctl("stats.arenas.0.lruns.0.nrequests", &nrequests, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.lruns.0.nrequests",
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
(void *)&nrequests, &sz, NULL, 0), expected,
|
||||||
|
"Unexpected mallctl() result");
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.lruns.0.curruns", &curruns, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.lruns.0.curruns", (void *)&curruns,
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
assert_u64_gt(nmalloc, 0,
|
assert_u64_gt(nmalloc, 0,
|
||||||
@@ -399,23 +405,26 @@ TEST_BEGIN(test_stats_arenas_hchunks)
|
|||||||
int expected = config_stats ? 0 : ENOENT;
|
int expected = config_stats ? 0 : ENOENT;
|
||||||
|
|
||||||
arena = 0;
|
arena = 0;
|
||||||
assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
|
assert_d_eq(mallctl("thread.arena", NULL, NULL, (void *)&arena,
|
||||||
0, "Unexpected mallctl() failure");
|
sizeof(arena)), 0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
p = mallocx(chunksize, 0);
|
p = mallocx(chunksize, 0);
|
||||||
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
assert_ptr_not_null(p, "Unexpected mallocx() failure");
|
||||||
|
|
||||||
assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
|
assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
|
||||||
"Unexpected mallctl() failure");
|
0, "Unexpected mallctl() failure");
|
||||||
|
|
||||||
sz = sizeof(uint64_t);
|
sz = sizeof(uint64_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.hchunks.0.nmalloc", &nmalloc, &sz,
|
assert_d_eq(mallctl("stats.arenas.0.hchunks.0.nmalloc",
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
(void *)&nmalloc, &sz, NULL, 0), expected,
|
||||||
assert_d_eq(mallctl("stats.arenas.0.hchunks.0.ndalloc", &ndalloc, &sz,
|
"Unexpected mallctl() result");
|
||||||
NULL, 0), expected, "Unexpected mallctl() result");
|
assert_d_eq(mallctl("stats.arenas.0.hchunks.0.ndalloc",
|
||||||
|
(void *)&ndalloc, &sz, NULL, 0), expected,
|
||||||
|
"Unexpected mallctl() result");
|
||||||
sz = sizeof(size_t);
|
sz = sizeof(size_t);
|
||||||
assert_d_eq(mallctl("stats.arenas.0.hchunks.0.curhchunks", &curhchunks,
|
assert_d_eq(mallctl("stats.arenas.0.hchunks.0.curhchunks",
|
||||||
&sz, NULL, 0), expected, "Unexpected mallctl() result");
|
(void *)&curhchunks, &sz, NULL, 0), expected,
|
||||||
|
"Unexpected mallctl() result");
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
assert_u64_gt(nmalloc, 0,
|
assert_u64_gt(nmalloc, 0,
|
||||||
|
|||||||
@@ -58,18 +58,18 @@ thd_start(void *arg)
|
|||||||
data_t d = (data_t)(uintptr_t)arg;
|
data_t d = (data_t)(uintptr_t)arg;
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
assert_x_eq(*data_tsd_get(), DATA_INIT,
|
assert_x_eq(*data_tsd_get(true), DATA_INIT,
|
||||||
"Initial tsd get should return initialization value");
|
"Initial tsd get should return initialization value");
|
||||||
|
|
||||||
p = malloc(1);
|
p = malloc(1);
|
||||||
assert_ptr_not_null(p, "Unexpected malloc() failure");
|
assert_ptr_not_null(p, "Unexpected malloc() failure");
|
||||||
|
|
||||||
data_tsd_set(&d);
|
data_tsd_set(&d);
|
||||||
assert_x_eq(*data_tsd_get(), d,
|
assert_x_eq(*data_tsd_get(true), d,
|
||||||
"After tsd set, tsd get should return value that was set");
|
"After tsd set, tsd get should return value that was set");
|
||||||
|
|
||||||
d = 0;
|
d = 0;
|
||||||
assert_x_eq(*data_tsd_get(), (data_t)(uintptr_t)arg,
|
assert_x_eq(*data_tsd_get(true), (data_t)(uintptr_t)arg,
|
||||||
"Resetting local data should have no effect on tsd");
|
"Resetting local data should have no effect on tsd");
|
||||||
|
|
||||||
free(p);
|
free(p);
|
||||||
@@ -79,7 +79,7 @@ thd_start(void *arg)
|
|||||||
TEST_BEGIN(test_tsd_main_thread)
|
TEST_BEGIN(test_tsd_main_thread)
|
||||||
{
|
{
|
||||||
|
|
||||||
thd_start((void *) 0xa5f3e329);
|
thd_start((void *)(uintptr_t)0xa5f3e329);
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ TEST_BEGIN(test_malloc_strtoumax)
|
|||||||
};
|
};
|
||||||
#define ERR(e) e, #e
|
#define ERR(e) e, #e
|
||||||
#define KUMAX(x) ((uintmax_t)x##ULL)
|
#define KUMAX(x) ((uintmax_t)x##ULL)
|
||||||
|
#define KSMAX(x) ((uintmax_t)(intmax_t)x##LL)
|
||||||
struct test_s tests[] = {
|
struct test_s tests[] = {
|
||||||
{"0", "0", -1, ERR(EINVAL), UINTMAX_MAX},
|
{"0", "0", -1, ERR(EINVAL), UINTMAX_MAX},
|
||||||
{"0", "0", 1, ERR(EINVAL), UINTMAX_MAX},
|
{"0", "0", 1, ERR(EINVAL), UINTMAX_MAX},
|
||||||
@@ -87,13 +88,13 @@ TEST_BEGIN(test_malloc_strtoumax)
|
|||||||
|
|
||||||
{"42", "", 0, ERR(0), KUMAX(42)},
|
{"42", "", 0, ERR(0), KUMAX(42)},
|
||||||
{"+42", "", 0, ERR(0), KUMAX(42)},
|
{"+42", "", 0, ERR(0), KUMAX(42)},
|
||||||
{"-42", "", 0, ERR(0), KUMAX(-42)},
|
{"-42", "", 0, ERR(0), KSMAX(-42)},
|
||||||
{"042", "", 0, ERR(0), KUMAX(042)},
|
{"042", "", 0, ERR(0), KUMAX(042)},
|
||||||
{"+042", "", 0, ERR(0), KUMAX(042)},
|
{"+042", "", 0, ERR(0), KUMAX(042)},
|
||||||
{"-042", "", 0, ERR(0), KUMAX(-042)},
|
{"-042", "", 0, ERR(0), KSMAX(-042)},
|
||||||
{"0x42", "", 0, ERR(0), KUMAX(0x42)},
|
{"0x42", "", 0, ERR(0), KUMAX(0x42)},
|
||||||
{"+0x42", "", 0, ERR(0), KUMAX(0x42)},
|
{"+0x42", "", 0, ERR(0), KUMAX(0x42)},
|
||||||
{"-0x42", "", 0, ERR(0), KUMAX(-0x42)},
|
{"-0x42", "", 0, ERR(0), KSMAX(-0x42)},
|
||||||
|
|
||||||
{"0", "", 0, ERR(0), KUMAX(0)},
|
{"0", "", 0, ERR(0), KUMAX(0)},
|
||||||
{"1", "", 0, ERR(0), KUMAX(1)},
|
{"1", "", 0, ERR(0), KUMAX(1)},
|
||||||
@@ -130,6 +131,7 @@ TEST_BEGIN(test_malloc_strtoumax)
|
|||||||
};
|
};
|
||||||
#undef ERR
|
#undef ERR
|
||||||
#undef KUMAX
|
#undef KUMAX
|
||||||
|
#undef KSMAX
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(tests)/sizeof(struct test_s); i++) {
|
for (i = 0; i < sizeof(tests)/sizeof(struct test_s); i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user