├── config.stamp.in ├── .gitattributes ├── test ├── src │ ├── math.c │ ├── btalloc_0.c │ ├── btalloc_1.c │ ├── btalloc.c │ ├── mq.c │ ├── thd.c │ ├── timer.c │ ├── mtx.c │ └── test.c ├── unit │ ├── junk_alloc.c │ ├── junk_free.c │ ├── a0.c │ ├── lg_chunk.c │ ├── prof_idump.c │ ├── mtx.c │ ├── fork.c │ ├── zero.c │ ├── mq.c │ ├── prof_accum.c │ ├── prof_gdump.c │ ├── ticker.c │ ├── tsd.c │ ├── quarantine.c │ ├── smoothstep.c │ ├── atomic.c │ ├── prof_thread_name.c │ ├── arena_reset.c │ └── prof_active.c ├── include │ └── test │ │ ├── thd.h │ │ ├── jemalloc_test_defs.h.in │ │ ├── timer.h │ │ ├── mtx.h │ │ ├── btalloc.h │ │ ├── mq.h │ │ ├── SFMT-params1279.h │ │ ├── SFMT-params2281.h │ │ ├── SFMT-params4253.h │ │ ├── SFMT-params607.h │ │ ├── SFMT-params19937.h │ │ ├── SFMT-params11213.h │ │ ├── SFMT-params132049.h │ │ ├── SFMT-params44497.h │ │ ├── SFMT-params86243.h │ │ └── SFMT-params216091.h ├── test.sh.in ├── integration │ ├── sdallocx.c │ ├── overflow.c │ ├── MALLOCX_ARENA.c │ ├── thread_arena.c │ ├── thread_tcache_enabled.c │ ├── posix_memalign.c │ ├── allocated.c │ └── aligned_alloc.c └── stress │ └── microbench.c ├── src ├── mb.c ├── hash.c ├── prng.c ├── spin.c ├── atomic.c ├── ticker.c ├── valgrind.c ├── extent.c ├── chunk_mmap.c ├── bitmap.c ├── witness.c ├── rtree.c └── nstime.c ├── msvc ├── projects │ └── vc2015 │ │ └── test_threads │ │ ├── test_threads.h │ │ ├── test_threads_main.cpp │ │ ├── test_threads.vcxproj.filters │ │ └── test_threads.cpp ├── ReadMe.txt └── jemalloc_vc2015.sln ├── .autom4te.cfg ├── include ├── jemalloc │ ├── internal │ │ ├── private_unnamespace.sh │ │ ├── private_namespace.sh │ │ ├── public_unnamespace.sh │ │ ├── public_namespace.sh │ │ ├── chunk_mmap.h │ │ ├── base.h │ │ ├── pages.h │ │ ├── assert.h │ │ ├── chunk_dss.h │ │ ├── spin.h │ │ ├── huge.h │ │ ├── quarantine.h │ │ ├── jemalloc_internal_macros.h │ │ ├── nstime.h │ │ ├── ticker.h │ │ ├── jemalloc_internal_decls.h │ │ ├── qr.h │ │ ├── ql.h │ │ ├── ckh.h │ │ ├── mb.h │ │ ├── chunk.h │ │ ├── ctl.h │ │ └── smoothstep.sh │ ├── jemalloc_rename.sh │ ├── jemalloc.sh │ ├── jemalloc_defs.h.in │ ├── jemalloc_mangle.sh │ ├── jemalloc_typedefs.h.in │ ├── jemalloc_protos.h.in │ └── jemalloc_macros.h.in └── msvc_compat │ ├── windows_extra.h │ ├── C99 │ └── stdbool.h │ └── strings.h ├── CMake_configure.cmd ├── bin ├── jemalloc.sh.in └── jemalloc-config.in ├── doc ├── manpages.xsl.in ├── html.xsl.in └── stylesheet.xsl ├── autogen.sh ├── coverage.sh ├── jemalloc.pc.in ├── .travis.yml ├── .appveyor.yml ├── README ├── COPYING └── .gitignore /config.stamp.in: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /test/src/math.c: -------------------------------------------------------------------------------- 1 | #define MATH_C_ 2 | #include "test/jemalloc_test.h" 3 | -------------------------------------------------------------------------------- /test/src/btalloc_0.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | btalloc_n_gen(0) 4 | -------------------------------------------------------------------------------- /test/src/btalloc_1.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | btalloc_n_gen(1) 4 | -------------------------------------------------------------------------------- /src/mb.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_MB_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | -------------------------------------------------------------------------------- /src/hash.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_HASH_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | -------------------------------------------------------------------------------- /src/prng.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_PRNG_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | -------------------------------------------------------------------------------- /src/spin.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_SPIN_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | -------------------------------------------------------------------------------- /msvc/projects/vc2015/test_threads/test_threads.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int test_threads(); 4 | -------------------------------------------------------------------------------- /src/atomic.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_ATOMIC_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | -------------------------------------------------------------------------------- /src/ticker.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_TICKER_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | -------------------------------------------------------------------------------- /test/unit/junk_alloc.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_TEST_JUNK_OPT "junk:alloc" 2 | #include "junk.c" 3 | #undef JEMALLOC_TEST_JUNK_OPT 4 | -------------------------------------------------------------------------------- /test/unit/junk_free.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_TEST_JUNK_OPT "junk:free" 2 | #include "junk.c" 3 | #undef JEMALLOC_TEST_JUNK_OPT 4 | -------------------------------------------------------------------------------- /.autom4te.cfg: -------------------------------------------------------------------------------- 1 | begin-language: "Autoconf-without-aclocal-m4" 2 | args: --no-cache 3 | end-language: "Autoconf-without-aclocal-m4" 4 | -------------------------------------------------------------------------------- /include/jemalloc/internal/private_unnamespace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for symbol in `cat $1` ; do 4 | echo "#undef ${symbol}" 5 | done 6 | -------------------------------------------------------------------------------- /CMake_configure.cmd: -------------------------------------------------------------------------------- 1 | REM Configure Jemalloc build with options 2 | 3 | CMake -G "Visual Studio 14 Win64" -Dwith-malloc-conf=purge:decay -Denable-debug=ON .. 4 | -------------------------------------------------------------------------------- /include/jemalloc/internal/private_namespace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for symbol in `cat $1` ; do 4 | echo "#define ${symbol} JEMALLOC_N(${symbol})" 5 | done 6 | -------------------------------------------------------------------------------- /test/src/btalloc.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | void * 4 | btalloc(size_t size, unsigned bits) 5 | { 6 | 7 | return (btalloc_0(size, bits)); 8 | } 9 | -------------------------------------------------------------------------------- /include/jemalloc/internal/public_unnamespace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for nm in `cat $1` ; do 4 | n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'` 5 | echo "#undef je_${n}" 6 | done 7 | -------------------------------------------------------------------------------- /include/msvc_compat/windows_extra.h: -------------------------------------------------------------------------------- 1 | #ifndef MSVC_COMPAT_WINDOWS_EXTRA_H 2 | #define MSVC_COMPAT_WINDOWS_EXTRA_H 3 | 4 | #include 5 | 6 | #endif /* MSVC_COMPAT_WINDOWS_EXTRA_H */ 7 | -------------------------------------------------------------------------------- /include/jemalloc/internal/public_namespace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for nm in `cat $1` ; do 4 | n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'` 5 | echo "#define je_${n} JEMALLOC_N(${n})" 6 | done 7 | -------------------------------------------------------------------------------- /bin/jemalloc.sh.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | prefix=@prefix@ 4 | exec_prefix=@exec_prefix@ 5 | libdir=@libdir@ 6 | 7 | @LD_PRELOAD_VAR@=${libdir}/libjemalloc.@SOREV@ 8 | export @LD_PRELOAD_VAR@ 9 | exec "$@" 10 | -------------------------------------------------------------------------------- /doc/manpages.xsl.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /doc/html.xsl.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/include/test/thd.h: -------------------------------------------------------------------------------- 1 | /* Abstraction layer for threading in tests. */ 2 | #ifdef _WIN32 3 | typedef HANDLE thd_t; 4 | #else 5 | typedef pthread_t thd_t; 6 | #endif 7 | 8 | void thd_create(thd_t *thd, void *(*proc)(void *), void *arg); 9 | void thd_join(thd_t thd, void **ret); 10 | -------------------------------------------------------------------------------- /msvc/projects/vc2015/test_threads/test_threads_main.cpp: -------------------------------------------------------------------------------- 1 | #include "test_threads.h" 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std::chrono_literals; 7 | 8 | int main(int argc, char** argv) 9 | { 10 | int rc = test_threads(); 11 | return rc; 12 | } 13 | -------------------------------------------------------------------------------- /test/unit/a0.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | TEST_BEGIN(test_a0) 4 | { 5 | void *p; 6 | 7 | p = a0malloc(1); 8 | assert_ptr_not_null(p, "Unexpected a0malloc() error"); 9 | a0dalloc(p); 10 | } 11 | TEST_END 12 | 13 | int 14 | main(void) 15 | { 16 | 17 | return (test_no_malloc_init( 18 | test_a0)); 19 | } 20 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for i in autoconf; do 4 | echo "$i" 5 | $i 6 | if [ $? -ne 0 ]; then 7 | echo "Error $? in $i" 8 | exit 1 9 | fi 10 | done 11 | 12 | echo "./configure --enable-autogen $@" 13 | ./configure --enable-autogen $@ 14 | if [ $? -ne 0 ]; then 15 | echo "Error $? in ./configure" 16 | exit 1 17 | fi 18 | -------------------------------------------------------------------------------- /test/include/test/jemalloc_test_defs.h.in: -------------------------------------------------------------------------------- 1 | #include "jemalloc/internal/jemalloc_internal_defs.h" 2 | #include "jemalloc/internal/jemalloc_internal_decls.h" 3 | 4 | /* 5 | * For use by SFMT. configure.ac doesn't actually define HAVE_SSE2 because its 6 | * dependencies are notoriously unportable in practice. 7 | */ 8 | #undef HAVE_SSE2 9 | #undef HAVE_ALTIVEC 10 | -------------------------------------------------------------------------------- /test/include/test/timer.h: -------------------------------------------------------------------------------- 1 | /* Simple timer, for use in benchmark reporting. */ 2 | 3 | typedef struct { 4 | nstime_t t0; 5 | nstime_t t1; 6 | } timedelta_t; 7 | 8 | void timer_start(timedelta_t *timer); 9 | void timer_stop(timedelta_t *timer); 10 | uint64_t timer_usec(const timedelta_t *timer); 11 | void timer_ratio(timedelta_t *a, timedelta_t *b, char *buf, size_t buflen); 12 | -------------------------------------------------------------------------------- /coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | objdir=$1 6 | suffix=$2 7 | shift 2 8 | objs=$@ 9 | 10 | gcov -b -p -f -o "${objdir}" ${objs} 11 | 12 | # Move gcov outputs so that subsequent gcov invocations won't clobber results 13 | # for the same sources with different compilation flags. 14 | for f in `find . -maxdepth 1 -type f -name '*.gcov'` ; do 15 | mv "${f}" "${f}.${suffix}" 16 | done 17 | -------------------------------------------------------------------------------- /jemalloc.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | install_suffix=@install_suffix@ 6 | 7 | Name: jemalloc 8 | Description: A general purpose malloc(3) implementation that emphasizes fragmentation avoidance and scalable concurrency support. 9 | URL: http://jemalloc.net/ 10 | Version: @jemalloc_version@ 11 | Cflags: -I${includedir} 12 | Libs: -L${libdir} -ljemalloc${install_suffix} 13 | -------------------------------------------------------------------------------- /doc/stylesheet.xsl: -------------------------------------------------------------------------------- 1 | 2 | ansi 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /include/msvc_compat/C99/stdbool.h: -------------------------------------------------------------------------------- 1 | #ifndef stdbool_h 2 | #define stdbool_h 3 | 4 | #include 5 | 6 | /* MSVC doesn't define _Bool or bool in C, but does have BOOL */ 7 | /* Note this doesn't pass autoconf's test because (bool) 0.5 != true */ 8 | /* Clang-cl uses MSVC headers, so needs msvc_compat, but has _Bool as 9 | * a built-in type. */ 10 | #ifndef __clang__ 11 | typedef BOOL _Bool; 12 | #endif 13 | 14 | #define bool _Bool 15 | #define true 1 16 | #define false 0 17 | 18 | #define __bool_true_false_are_defined 1 19 | 20 | #endif /* stdbool_h */ 21 | -------------------------------------------------------------------------------- /include/jemalloc/jemalloc_rename.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | public_symbols_txt=$1 4 | 5 | cat < 7 | 8 | void 9 | valgrind_make_mem_noaccess(void *ptr, size_t usize) 10 | { 11 | 12 | VALGRIND_MAKE_MEM_NOACCESS(ptr, usize); 13 | } 14 | 15 | void 16 | valgrind_make_mem_undefined(void *ptr, size_t usize) 17 | { 18 | 19 | VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize); 20 | } 21 | 22 | void 23 | valgrind_make_mem_defined(void *ptr, size_t usize) 24 | { 25 | 26 | VALGRIND_MAKE_MEM_DEFINED(ptr, usize); 27 | } 28 | 29 | void 30 | valgrind_freelike_block(void *ptr, size_t usize) 31 | { 32 | 33 | VALGRIND_FREELIKE_BLOCK(ptr, usize); 34 | } 35 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | 3 | environment: 4 | matrix: 5 | - MSYSTEM: MINGW64 6 | CPU: x86_64 7 | MSVC: amd64 8 | - MSYSTEM: MINGW32 9 | CPU: i686 10 | MSVC: x86 11 | - MSYSTEM: MINGW64 12 | CPU: x86_64 13 | - MSYSTEM: MINGW32 14 | CPU: i686 15 | 16 | install: 17 | - set PATH=c:\msys64\%MSYSTEM%\bin;c:\msys64\usr\bin;%PATH% 18 | - if defined MSVC call "c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %MSVC% 19 | - if defined MSVC pacman --noconfirm -Rsc mingw-w64-%CPU%-gcc gcc 20 | - pacman --noconfirm -Suy mingw-w64-%CPU%-make 21 | 22 | build_script: 23 | - bash -c "autoconf" 24 | - bash -c "./configure" 25 | - mingw32-make -j3 26 | - file lib/jemalloc.dll 27 | - mingw32-make -j3 tests 28 | - mingw32-make -k check 29 | -------------------------------------------------------------------------------- /include/jemalloc/internal/chunk_mmap.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | #endif /* JEMALLOC_H_TYPES */ 5 | /******************************************************************************/ 6 | #ifdef JEMALLOC_H_STRUCTS 7 | 8 | #endif /* JEMALLOC_H_STRUCTS */ 9 | /******************************************************************************/ 10 | #ifdef JEMALLOC_H_EXTERNS 11 | 12 | void *chunk_alloc_mmap(void *new_addr, size_t size, size_t alignment, 13 | bool *zero, bool *commit); 14 | bool chunk_dalloc_mmap(void *chunk, size_t size); 15 | 16 | #endif /* JEMALLOC_H_EXTERNS */ 17 | /******************************************************************************/ 18 | #ifdef JEMALLOC_H_INLINES 19 | 20 | #endif /* JEMALLOC_H_INLINES */ 21 | /******************************************************************************/ 22 | -------------------------------------------------------------------------------- /test/src/thd.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #ifdef _WIN32 4 | void 5 | thd_create(thd_t *thd, void *(*proc)(void *), void *arg) 6 | { 7 | LPTHREAD_START_ROUTINE routine = (LPTHREAD_START_ROUTINE)proc; 8 | *thd = CreateThread(NULL, 0, routine, arg, 0, NULL); 9 | if (*thd == NULL) 10 | test_fail("Error in CreateThread()\n"); 11 | } 12 | 13 | void 14 | thd_join(thd_t thd, void **ret) 15 | { 16 | 17 | if (WaitForSingleObject(thd, INFINITE) == WAIT_OBJECT_0 && ret) { 18 | DWORD exit_code; 19 | GetExitCodeThread(thd, (LPDWORD) &exit_code); 20 | *ret = (void *)(uintptr_t)exit_code; 21 | } 22 | } 23 | 24 | #else 25 | void 26 | thd_create(thd_t *thd, void *(*proc)(void *), void *arg) 27 | { 28 | 29 | if (pthread_create(thd, NULL, proc, arg) != 0) 30 | test_fail("Error in pthread_create()\n"); 31 | } 32 | 33 | void 34 | thd_join(thd_t thd, void **ret) 35 | { 36 | 37 | pthread_join(thd, ret); 38 | } 39 | #endif 40 | -------------------------------------------------------------------------------- /test/include/test/btalloc.h: -------------------------------------------------------------------------------- 1 | /* btalloc() provides a mechanism for allocating via permuted backtraces. */ 2 | void *btalloc(size_t size, unsigned bits); 3 | 4 | #define btalloc_n_proto(n) \ 5 | void *btalloc_##n(size_t size, unsigned bits); 6 | btalloc_n_proto(0) 7 | btalloc_n_proto(1) 8 | 9 | #define btalloc_n_gen(n) \ 10 | void * \ 11 | btalloc_##n(size_t size, unsigned bits) \ 12 | { \ 13 | void *p; \ 14 | \ 15 | if (bits == 0) \ 16 | p = mallocx(size, 0); \ 17 | else { \ 18 | switch (bits & 0x1U) { \ 19 | case 0: \ 20 | p = (btalloc_0(size, bits >> 1)); \ 21 | break; \ 22 | case 1: \ 23 | p = (btalloc_1(size, bits >> 1)); \ 24 | break; \ 25 | default: not_reached(); \ 26 | } \ 27 | } \ 28 | /* Intentionally sabotage tail call optimization. */ \ 29 | assert_ptr_not_null(p, "Unexpected mallocx() failure"); \ 30 | return (p); \ 31 | } 32 | -------------------------------------------------------------------------------- /include/jemalloc/internal/base.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | #endif /* JEMALLOC_H_TYPES */ 5 | /******************************************************************************/ 6 | #ifdef JEMALLOC_H_STRUCTS 7 | 8 | #endif /* JEMALLOC_H_STRUCTS */ 9 | /******************************************************************************/ 10 | #ifdef JEMALLOC_H_EXTERNS 11 | 12 | void *base_alloc(tsdn_t *tsdn, size_t size); 13 | void base_stats_get(tsdn_t *tsdn, size_t *allocated, size_t *resident, 14 | size_t *mapped); 15 | bool base_boot(void); 16 | void base_prefork(tsdn_t *tsdn); 17 | void base_postfork_parent(tsdn_t *tsdn); 18 | void base_postfork_child(tsdn_t *tsdn); 19 | 20 | #endif /* JEMALLOC_H_EXTERNS */ 21 | /******************************************************************************/ 22 | #ifdef JEMALLOC_H_INLINES 23 | 24 | #endif /* JEMALLOC_H_INLINES */ 25 | /******************************************************************************/ 26 | -------------------------------------------------------------------------------- /msvc/projects/vc2015/test_threads/test_threads.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /include/jemalloc/internal/pages.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | #endif /* JEMALLOC_H_TYPES */ 5 | /******************************************************************************/ 6 | #ifdef JEMALLOC_H_STRUCTS 7 | 8 | #endif /* JEMALLOC_H_STRUCTS */ 9 | /******************************************************************************/ 10 | #ifdef JEMALLOC_H_EXTERNS 11 | 12 | void *pages_map(void *addr, size_t size, bool *commit); 13 | void pages_unmap(void *addr, size_t size); 14 | void *pages_trim(void *addr, size_t alloc_size, size_t leadsize, 15 | size_t size, bool *commit); 16 | bool pages_commit(void *addr, size_t size); 17 | bool pages_decommit(void *addr, size_t size); 18 | bool pages_purge(void *addr, size_t size); 19 | void pages_boot(void); 20 | 21 | #endif /* JEMALLOC_H_EXTERNS */ 22 | /******************************************************************************/ 23 | #ifdef JEMALLOC_H_INLINES 24 | 25 | #endif /* JEMALLOC_H_INLINES */ 26 | /******************************************************************************/ 27 | 28 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | jemalloc is a general purpose malloc(3) implementation that emphasizes 2 | fragmentation avoidance and scalable concurrency support. jemalloc first came 3 | into use as the FreeBSD libc allocator in 2005, and since then it has found its 4 | way into numerous applications that rely on its predictable behavior. In 2010 5 | jemalloc development efforts broadened to include developer support features 6 | such as heap profiling, Valgrind integration, and extensive monitoring/tuning 7 | hooks. Modern jemalloc releases continue to be integrated back into FreeBSD, 8 | and therefore versatility remains critical. Ongoing development efforts trend 9 | toward making jemalloc among the best allocators for a broad range of demanding 10 | applications, and eliminating/mitigating weaknesses that have practical 11 | repercussions for real world applications. 12 | 13 | The COPYING file contains copyright and licensing information. 14 | 15 | The INSTALL file contains information on how to configure, build, and install 16 | jemalloc. 17 | 18 | The ChangeLog file contains a brief summary of changes for each release. 19 | 20 | URL: http://jemalloc.net/ 21 | -------------------------------------------------------------------------------- /test/unit/prof_idump.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #ifdef JEMALLOC_PROF 4 | const char *malloc_conf = 5 | "prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0," 6 | "lg_prof_interval:0"; 7 | #endif 8 | 9 | static bool did_prof_dump_open; 10 | 11 | static int 12 | prof_dump_open_intercept(bool propagate_err, const char *filename) 13 | { 14 | int fd; 15 | 16 | did_prof_dump_open = true; 17 | 18 | fd = open("/dev/null", O_WRONLY); 19 | assert_d_ne(fd, -1, "Unexpected open() failure"); 20 | 21 | return (fd); 22 | } 23 | 24 | TEST_BEGIN(test_idump) 25 | { 26 | bool active; 27 | void *p; 28 | 29 | test_skip_if(!config_prof); 30 | 31 | active = true; 32 | assert_d_eq(mallctl("prof.active", NULL, NULL, &active, sizeof(active)), 33 | 0, "Unexpected mallctl failure while activating profiling"); 34 | 35 | prof_dump_open = prof_dump_open_intercept; 36 | 37 | did_prof_dump_open = false; 38 | p = mallocx(1, 0); 39 | assert_ptr_not_null(p, "Unexpected mallocx() failure"); 40 | dallocx(p, 0); 41 | assert_true(did_prof_dump_open, "Expected a profile dump"); 42 | } 43 | TEST_END 44 | 45 | int 46 | main(void) 47 | { 48 | 49 | return (test( 50 | test_idump)); 51 | } 52 | -------------------------------------------------------------------------------- /test/test.sh.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | case @abi@ in 4 | macho) 5 | export DYLD_FALLBACK_LIBRARY_PATH="@objroot@lib" 6 | ;; 7 | pecoff) 8 | export PATH="${PATH}:@objroot@lib" 9 | ;; 10 | *) 11 | ;; 12 | esac 13 | 14 | # Corresponds to test_status_t. 15 | pass_code=0 16 | skip_code=1 17 | fail_code=2 18 | 19 | pass_count=0 20 | skip_count=0 21 | fail_count=0 22 | for t in $@; do 23 | if [ $pass_count -ne 0 -o $skip_count -ne 0 -o $fail_count != 0 ] ; then 24 | echo 25 | fi 26 | echo "=== ${t} ===" 27 | ${t}@exe@ @abs_srcroot@ @abs_objroot@ 28 | result_code=$? 29 | case ${result_code} in 30 | ${pass_code}) 31 | pass_count=$((pass_count+1)) 32 | ;; 33 | ${skip_code}) 34 | skip_count=$((skip_count+1)) 35 | ;; 36 | ${fail_code}) 37 | fail_count=$((fail_count+1)) 38 | ;; 39 | *) 40 | echo "Test harness error" 1>&2 41 | exit 1 42 | esac 43 | done 44 | 45 | total_count=`expr ${pass_count} + ${skip_count} + ${fail_count}` 46 | echo 47 | echo "Test suite summary: pass: ${pass_count}/${total_count}, skip: ${skip_count}/${total_count}, fail: ${fail_count}/${total_count}" 48 | 49 | if [ ${fail_count} -eq 0 ] ; then 50 | exit 0 51 | else 52 | exit 1 53 | fi 54 | -------------------------------------------------------------------------------- /include/jemalloc/internal/assert.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Define a custom assert() in order to reduce the chances of deadlock during 3 | * assertion failure. 4 | */ 5 | #ifndef assert 6 | #define assert(e) do { \ 7 | if (unlikely(config_debug && !(e))) { \ 8 | malloc_printf( \ 9 | ": %s:%d: Failed assertion: \"%s\"\n", \ 10 | __FILE__, __LINE__, #e); \ 11 | abort(); \ 12 | } \ 13 | } while (0) 14 | #endif 15 | 16 | #ifndef not_reached 17 | #define not_reached() do { \ 18 | if (config_debug) { \ 19 | malloc_printf( \ 20 | ": %s:%d: Unreachable code reached\n", \ 21 | __FILE__, __LINE__); \ 22 | abort(); \ 23 | } \ 24 | unreachable(); \ 25 | } while (0) 26 | #endif 27 | 28 | #ifndef not_implemented 29 | #define not_implemented() do { \ 30 | if (config_debug) { \ 31 | malloc_printf(": %s:%d: Not implemented\n", \ 32 | __FILE__, __LINE__); \ 33 | abort(); \ 34 | } \ 35 | } while (0) 36 | #endif 37 | 38 | #ifndef assert_not_implemented 39 | #define assert_not_implemented(e) do { \ 40 | if (unlikely(config_debug && !(e))) \ 41 | not_implemented(); \ 42 | } while (0) 43 | #endif 44 | 45 | 46 | -------------------------------------------------------------------------------- /test/unit/mtx.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define NTHREADS 2 4 | #define NINCRS 2000000 5 | 6 | TEST_BEGIN(test_mtx_basic) 7 | { 8 | mtx_t mtx; 9 | 10 | assert_false(mtx_init(&mtx), "Unexpected mtx_init() failure"); 11 | mtx_lock(&mtx); 12 | mtx_unlock(&mtx); 13 | mtx_fini(&mtx); 14 | } 15 | TEST_END 16 | 17 | typedef struct { 18 | mtx_t mtx; 19 | unsigned x; 20 | } thd_start_arg_t; 21 | 22 | static void * 23 | thd_start(void *varg) 24 | { 25 | thd_start_arg_t *arg = (thd_start_arg_t *)varg; 26 | unsigned i; 27 | 28 | for (i = 0; i < NINCRS; i++) { 29 | mtx_lock(&arg->mtx); 30 | arg->x++; 31 | mtx_unlock(&arg->mtx); 32 | } 33 | return (NULL); 34 | } 35 | 36 | TEST_BEGIN(test_mtx_race) 37 | { 38 | thd_start_arg_t arg; 39 | thd_t thds[NTHREADS]; 40 | unsigned i; 41 | 42 | assert_false(mtx_init(&arg.mtx), "Unexpected mtx_init() failure"); 43 | arg.x = 0; 44 | for (i = 0; i < NTHREADS; i++) 45 | thd_create(&thds[i], thd_start, (void *)&arg); 46 | for (i = 0; i < NTHREADS; i++) 47 | thd_join(thds[i], NULL); 48 | assert_u_eq(arg.x, NTHREADS * NINCRS, 49 | "Race-related counter corruption"); 50 | } 51 | TEST_END 52 | 53 | int 54 | main(void) 55 | { 56 | 57 | return (test( 58 | test_mtx_basic, 59 | test_mtx_race)); 60 | } 61 | -------------------------------------------------------------------------------- /test/integration/sdallocx.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define MAXALIGN (((size_t)1) << 25) 4 | #define NITER 4 5 | 6 | TEST_BEGIN(test_basic) 7 | { 8 | void *ptr = mallocx(64, 0); 9 | sdallocx(ptr, 64, 0); 10 | } 11 | TEST_END 12 | 13 | TEST_BEGIN(test_alignment_and_size) 14 | { 15 | size_t nsz, sz, alignment, total; 16 | unsigned i; 17 | void *ps[NITER]; 18 | 19 | for (i = 0; i < NITER; i++) 20 | ps[i] = NULL; 21 | 22 | for (alignment = 8; 23 | alignment <= MAXALIGN; 24 | alignment <<= 1) { 25 | total = 0; 26 | for (sz = 1; 27 | sz < 3 * alignment && sz < (1U << 31); 28 | sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { 29 | for (i = 0; i < NITER; i++) { 30 | nsz = nallocx(sz, MALLOCX_ALIGN(alignment) | 31 | MALLOCX_ZERO); 32 | ps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) | 33 | MALLOCX_ZERO); 34 | total += nsz; 35 | if (total >= (MAXALIGN << 1)) 36 | break; 37 | } 38 | for (i = 0; i < NITER; i++) { 39 | if (ps[i] != NULL) { 40 | sdallocx(ps[i], sz, 41 | MALLOCX_ALIGN(alignment)); 42 | ps[i] = NULL; 43 | } 44 | } 45 | } 46 | } 47 | } 48 | TEST_END 49 | 50 | int 51 | main(void) 52 | { 53 | 54 | return (test( 55 | test_basic, 56 | test_alignment_and_size)); 57 | } 58 | -------------------------------------------------------------------------------- /include/msvc_compat/strings.h: -------------------------------------------------------------------------------- 1 | #ifndef strings_h 2 | #define strings_h 3 | 4 | /* MSVC doesn't define ffs/ffsl. This dummy strings.h header is provided 5 | * for both */ 6 | #ifdef _MSC_VER 7 | # include 8 | # pragma intrinsic(_BitScanForward) 9 | static __forceinline int ffsl(long x) 10 | { 11 | unsigned long i; 12 | 13 | if (_BitScanForward(&i, x)) 14 | return (i + 1); 15 | return (0); 16 | } 17 | 18 | static __forceinline int ffs(int x) 19 | { 20 | 21 | return (ffsl(x)); 22 | } 23 | 24 | # ifdef _M_X64 25 | # pragma intrinsic(_BitScanForward64) 26 | # endif 27 | 28 | static __forceinline int ffsll(unsigned __int64 x) 29 | { 30 | unsigned long i; 31 | #ifdef _M_X64 32 | if (_BitScanForward64(&i, x)) 33 | return (i + 1); 34 | return (0); 35 | #else 36 | // Fallback for 32-bit build where 64-bit version not available 37 | // assuming little endian 38 | union { 39 | unsigned __int64 ll; 40 | unsigned long l[2]; 41 | } s; 42 | 43 | s.ll = x; 44 | 45 | if (_BitScanForward(&i, s.l[0])) 46 | return (i + 1); 47 | else if(_BitScanForward(&i, s.l[1])) 48 | return (i + 33); 49 | return (0); 50 | #endif 51 | } 52 | 53 | #else 54 | # define ffsll(x) __builtin_ffsll(x) 55 | # define ffsl(x) __builtin_ffsl(x) 56 | # define ffs(x) __builtin_ffs(x) 57 | #endif 58 | 59 | #endif /* strings_h */ 60 | -------------------------------------------------------------------------------- /test/unit/fork.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #ifndef _WIN32 4 | #include 5 | #endif 6 | 7 | TEST_BEGIN(test_fork) 8 | { 9 | #ifndef _WIN32 10 | void *p; 11 | pid_t pid; 12 | 13 | p = malloc(1); 14 | assert_ptr_not_null(p, "Unexpected malloc() failure"); 15 | 16 | pid = fork(); 17 | 18 | free(p); 19 | 20 | p = malloc(64); 21 | assert_ptr_not_null(p, "Unexpected malloc() failure"); 22 | free(p); 23 | 24 | if (pid == -1) { 25 | /* Error. */ 26 | test_fail("Unexpected fork() failure"); 27 | } else if (pid == 0) { 28 | /* Child. */ 29 | _exit(0); 30 | } else { 31 | int status; 32 | 33 | /* Parent. */ 34 | while (true) { 35 | if (waitpid(pid, &status, 0) == -1) 36 | test_fail("Unexpected waitpid() failure"); 37 | if (WIFSIGNALED(status)) { 38 | test_fail("Unexpected child termination due to " 39 | "signal %d", WTERMSIG(status)); 40 | break; 41 | } 42 | if (WIFEXITED(status)) { 43 | if (WEXITSTATUS(status) != 0) { 44 | test_fail( 45 | "Unexpected child exit value %d", 46 | WEXITSTATUS(status)); 47 | } 48 | break; 49 | } 50 | } 51 | } 52 | #else 53 | test_skip("fork(2) is irrelevant to Windows"); 54 | #endif 55 | } 56 | TEST_END 57 | 58 | int 59 | main(void) 60 | { 61 | 62 | return (test( 63 | test_fork)); 64 | } 65 | -------------------------------------------------------------------------------- /test/src/timer.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | void 4 | timer_start(timedelta_t *timer) 5 | { 6 | 7 | nstime_init(&timer->t0, 0); 8 | nstime_update(&timer->t0); 9 | } 10 | 11 | void 12 | timer_stop(timedelta_t *timer) 13 | { 14 | 15 | nstime_copy(&timer->t1, &timer->t0); 16 | nstime_update(&timer->t1); 17 | } 18 | 19 | uint64_t 20 | timer_usec(const timedelta_t *timer) 21 | { 22 | nstime_t delta; 23 | 24 | nstime_copy(&delta, &timer->t1); 25 | nstime_subtract(&delta, &timer->t0); 26 | return (nstime_ns(&delta) / 1000); 27 | } 28 | 29 | void 30 | timer_ratio(timedelta_t *a, timedelta_t *b, char *buf, size_t buflen) 31 | { 32 | uint64_t t0 = timer_usec(a); 33 | uint64_t t1 = timer_usec(b); 34 | uint64_t mult; 35 | size_t i = 0; 36 | size_t j, n; 37 | 38 | /* Whole. */ 39 | n = malloc_snprintf(&buf[i], buflen-i, "%"FMTu64, t0 / t1); 40 | i += n; 41 | if (i >= buflen) 42 | return; 43 | mult = 1; 44 | for (j = 0; j < n; j++) 45 | mult *= 10; 46 | 47 | /* Decimal. */ 48 | n = malloc_snprintf(&buf[i], buflen-i, "."); 49 | i += n; 50 | 51 | /* Fraction. */ 52 | while (i < buflen-1) { 53 | uint64_t round = (i+1 == buflen-1 && ((t0 * mult * 10 / t1) % 10 54 | >= 5)) ? 1 : 0; 55 | n = malloc_snprintf(&buf[i], buflen-i, 56 | "%"FMTu64, (t0 * mult / t1) % 10 + round); 57 | i += n; 58 | mult *= 10; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /include/jemalloc/jemalloc_defs.h.in: -------------------------------------------------------------------------------- 1 | /* Defined if __attribute__((...)) syntax is supported. */ 2 | #undef JEMALLOC_HAVE_ATTR 3 | 4 | /* Defined if alloc_size attribute is supported. */ 5 | #undef JEMALLOC_HAVE_ATTR_ALLOC_SIZE 6 | 7 | /* Defined if format(gnu_printf, ...) attribute is supported. */ 8 | #undef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF 9 | 10 | /* Defined if format(printf, ...) attribute is supported. */ 11 | #undef JEMALLOC_HAVE_ATTR_FORMAT_PRINTF 12 | 13 | /* 14 | * Define overrides for non-standard allocator-related functions if they are 15 | * present on the system. 16 | */ 17 | #undef JEMALLOC_OVERRIDE_MEMALIGN 18 | #undef JEMALLOC_OVERRIDE_VALLOC 19 | 20 | /* 21 | * At least Linux omits the "const" in: 22 | * 23 | * size_t malloc_usable_size(const void *ptr); 24 | * 25 | * Match the operating system's prototype. 26 | */ 27 | #undef JEMALLOC_USABLE_SIZE_CONST 28 | 29 | /* 30 | * If defined, specify throw() for the public function prototypes when compiling 31 | * with C++. The only justification for this is to match the prototypes that 32 | * glibc defines. 33 | */ 34 | #undef JEMALLOC_USE_CXX_THROW 35 | 36 | #ifdef _MSC_VER 37 | # ifdef _WIN64 38 | # define LG_SIZEOF_PTR_WIN 3 39 | # else 40 | # define LG_SIZEOF_PTR_WIN 2 41 | # endif 42 | #endif 43 | 44 | /* sizeof(void *) == 2^LG_SIZEOF_PTR. */ 45 | #undef LG_SIZEOF_PTR 46 | -------------------------------------------------------------------------------- /include/jemalloc/internal/chunk_dss.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | typedef enum { 5 | dss_prec_disabled = 0, 6 | dss_prec_primary = 1, 7 | dss_prec_secondary = 2, 8 | 9 | dss_prec_limit = 3 10 | } dss_prec_t; 11 | #define DSS_PREC_DEFAULT dss_prec_secondary 12 | #define DSS_DEFAULT "secondary" 13 | 14 | #endif /* JEMALLOC_H_TYPES */ 15 | /******************************************************************************/ 16 | #ifdef JEMALLOC_H_STRUCTS 17 | 18 | extern const char *dss_prec_names[]; 19 | 20 | #endif /* JEMALLOC_H_STRUCTS */ 21 | /******************************************************************************/ 22 | #ifdef JEMALLOC_H_EXTERNS 23 | 24 | dss_prec_t chunk_dss_prec_get(void); 25 | bool chunk_dss_prec_set(dss_prec_t dss_prec); 26 | void *chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, 27 | size_t size, size_t alignment, bool *zero, bool *commit); 28 | bool chunk_in_dss(void *chunk); 29 | bool chunk_dss_mergeable(void *chunk_a, void *chunk_b); 30 | void chunk_dss_boot(void); 31 | 32 | #endif /* JEMALLOC_H_EXTERNS */ 33 | /******************************************************************************/ 34 | #ifdef JEMALLOC_H_INLINES 35 | 36 | #endif /* JEMALLOC_H_INLINES */ 37 | /******************************************************************************/ 38 | -------------------------------------------------------------------------------- /include/jemalloc/internal/spin.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | typedef struct spin_s spin_t; 5 | 6 | #endif /* JEMALLOC_H_TYPES */ 7 | /******************************************************************************/ 8 | #ifdef JEMALLOC_H_STRUCTS 9 | 10 | struct spin_s { 11 | unsigned iteration; 12 | }; 13 | 14 | #endif /* JEMALLOC_H_STRUCTS */ 15 | /******************************************************************************/ 16 | #ifdef JEMALLOC_H_EXTERNS 17 | 18 | #endif /* JEMALLOC_H_EXTERNS */ 19 | /******************************************************************************/ 20 | #ifdef JEMALLOC_H_INLINES 21 | 22 | #ifndef JEMALLOC_ENABLE_INLINE 23 | void spin_init(spin_t *spin); 24 | void spin_adaptive(spin_t *spin); 25 | #endif 26 | 27 | #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_SPIN_C_)) 28 | JEMALLOC_INLINE void 29 | spin_init(spin_t *spin) 30 | { 31 | 32 | spin->iteration = 0; 33 | } 34 | 35 | JEMALLOC_INLINE void 36 | spin_adaptive(spin_t *spin) 37 | { 38 | volatile uint64_t i; 39 | 40 | for (i = 0; i < (KQU(1) << spin->iteration); i++) 41 | CPU_SPINWAIT; 42 | 43 | if (spin->iteration < 63) 44 | spin->iteration++; 45 | } 46 | 47 | #endif 48 | 49 | #endif /* JEMALLOC_H_INLINES */ 50 | /******************************************************************************/ 51 | 52 | -------------------------------------------------------------------------------- /include/jemalloc/jemalloc_mangle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | public_symbols_txt=$1 4 | symbol_prefix=$2 5 | 6 | cat <lock, _CRT_SPINCOUNT)) 13 | return (true); 14 | #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) 15 | mtx->lock = OS_UNFAIR_LOCK_INIT; 16 | #elif (defined(JEMALLOC_OSSPIN)) 17 | mtx->lock = 0; 18 | #else 19 | pthread_mutexattr_t attr; 20 | 21 | if (pthread_mutexattr_init(&attr) != 0) 22 | return (true); 23 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT); 24 | if (pthread_mutex_init(&mtx->lock, &attr) != 0) { 25 | pthread_mutexattr_destroy(&attr); 26 | return (true); 27 | } 28 | pthread_mutexattr_destroy(&attr); 29 | #endif 30 | return (false); 31 | } 32 | 33 | void 34 | mtx_fini(mtx_t *mtx) 35 | { 36 | 37 | #ifdef _WIN32 38 | #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) 39 | #elif (defined(JEMALLOC_OSSPIN)) 40 | #else 41 | pthread_mutex_destroy(&mtx->lock); 42 | #endif 43 | } 44 | 45 | void 46 | mtx_lock(mtx_t *mtx) 47 | { 48 | 49 | #ifdef _WIN32 50 | EnterCriticalSection(&mtx->lock); 51 | #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) 52 | os_unfair_lock_lock(&mtx->lock); 53 | #elif (defined(JEMALLOC_OSSPIN)) 54 | OSSpinLockLock(&mtx->lock); 55 | #else 56 | pthread_mutex_lock(&mtx->lock); 57 | #endif 58 | } 59 | 60 | void 61 | mtx_unlock(mtx_t *mtx) 62 | { 63 | 64 | #ifdef _WIN32 65 | LeaveCriticalSection(&mtx->lock); 66 | #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) 67 | os_unfair_lock_unlock(&mtx->lock); 68 | #elif (defined(JEMALLOC_OSSPIN)) 69 | OSSpinLockUnlock(&mtx->lock); 70 | #else 71 | pthread_mutex_unlock(&mtx->lock); 72 | #endif 73 | } 74 | -------------------------------------------------------------------------------- /src/extent.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_EXTENT_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | /******************************************************************************/ 5 | 6 | JEMALLOC_INLINE_C size_t 7 | extent_quantize(size_t size) 8 | { 9 | 10 | /* 11 | * Round down to the nearest chunk size that can actually be requested 12 | * during normal huge allocation. 13 | */ 14 | return (index2size(size2index(size + 1) - 1)); 15 | } 16 | 17 | JEMALLOC_INLINE_C int 18 | extent_szad_comp(const extent_node_t *a, const extent_node_t *b) 19 | { 20 | int ret; 21 | size_t a_qsize = extent_quantize(extent_node_size_get(a)); 22 | size_t b_qsize = extent_quantize(extent_node_size_get(b)); 23 | 24 | /* 25 | * Compare based on quantized size rather than size, in order to sort 26 | * equally useful extents only by address. 27 | */ 28 | ret = (a_qsize > b_qsize) - (a_qsize < b_qsize); 29 | if (ret == 0) { 30 | uintptr_t a_addr = (uintptr_t)extent_node_addr_get(a); 31 | uintptr_t b_addr = (uintptr_t)extent_node_addr_get(b); 32 | 33 | ret = (a_addr > b_addr) - (a_addr < b_addr); 34 | } 35 | 36 | return (ret); 37 | } 38 | 39 | /* Generate red-black tree functions. */ 40 | rb_gen(, extent_tree_szad_, extent_tree_t, extent_node_t, szad_link, 41 | extent_szad_comp) 42 | 43 | JEMALLOC_INLINE_C int 44 | extent_ad_comp(const extent_node_t *a, const extent_node_t *b) 45 | { 46 | uintptr_t a_addr = (uintptr_t)extent_node_addr_get(a); 47 | uintptr_t b_addr = (uintptr_t)extent_node_addr_get(b); 48 | 49 | return ((a_addr > b_addr) - (a_addr < b_addr)); 50 | } 51 | 52 | /* Generate red-black tree functions. */ 53 | rb_gen(, extent_tree_ad_, extent_tree_t, extent_node_t, ad_link, extent_ad_comp) 54 | -------------------------------------------------------------------------------- /test/integration/MALLOCX_ARENA.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define NTHREADS 10 4 | 5 | static bool have_dss = 6 | #ifdef JEMALLOC_DSS 7 | true 8 | #else 9 | false 10 | #endif 11 | ; 12 | 13 | void * 14 | thd_start(void *arg) 15 | { 16 | unsigned thread_ind = (unsigned)(uintptr_t)arg; 17 | unsigned arena_ind; 18 | void *p; 19 | size_t sz; 20 | 21 | sz = sizeof(arena_ind); 22 | assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0, 23 | "Error in arenas.extend"); 24 | 25 | if (thread_ind % 4 != 3) { 26 | size_t mib[3]; 27 | size_t miblen = sizeof(mib) / sizeof(size_t); 28 | const char *dss_precs[] = {"disabled", "primary", "secondary"}; 29 | unsigned prec_ind = thread_ind % 30 | (sizeof(dss_precs)/sizeof(char*)); 31 | const char *dss = dss_precs[prec_ind]; 32 | int expected_err = (have_dss || prec_ind == 0) ? 0 : EFAULT; 33 | assert_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0, 34 | "Error in mallctlnametomib()"); 35 | mib[1] = arena_ind; 36 | assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&dss, 37 | sizeof(const char *)), expected_err, 38 | "Error in mallctlbymib()"); 39 | } 40 | 41 | p = mallocx(1, MALLOCX_ARENA(arena_ind)); 42 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 43 | dallocx(p, 0); 44 | 45 | return (NULL); 46 | } 47 | 48 | TEST_BEGIN(test_MALLOCX_ARENA) 49 | { 50 | thd_t thds[NTHREADS]; 51 | unsigned i; 52 | 53 | for (i = 0; i < NTHREADS; i++) { 54 | thd_create(&thds[i], thd_start, 55 | (void *)(uintptr_t)i); 56 | } 57 | 58 | for (i = 0; i < NTHREADS; i++) 59 | thd_join(thds[i], NULL); 60 | } 61 | TEST_END 62 | 63 | int 64 | main(void) 65 | { 66 | 67 | return (test( 68 | test_MALLOCX_ARENA)); 69 | } 70 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Unless otherwise specified, files in the jemalloc source distribution are 2 | subject to the following license: 3 | -------------------------------------------------------------------------------- 4 | Copyright (C) 2002-2016 Jason Evans . 5 | All rights reserved. 6 | Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved. 7 | Copyright (C) 2009-2016 Facebook, Inc. All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 1. Redistributions of source code must retain the above copyright notice(s), 12 | this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright notice(s), 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS 18 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- 28 | -------------------------------------------------------------------------------- /include/jemalloc/jemalloc_typedefs.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * void * 3 | * chunk_alloc(void *new_addr, size_t size, size_t alignment, bool *zero, 4 | * bool *commit, unsigned arena_ind); 5 | */ 6 | typedef void *(chunk_alloc_t)(void *, size_t, size_t, bool *, bool *, unsigned); 7 | 8 | /* 9 | * bool 10 | * chunk_dalloc(void *chunk, size_t size, bool committed, unsigned arena_ind); 11 | */ 12 | typedef bool (chunk_dalloc_t)(void *, size_t, bool, unsigned); 13 | 14 | /* 15 | * bool 16 | * chunk_commit(void *chunk, size_t size, size_t offset, size_t length, 17 | * unsigned arena_ind); 18 | */ 19 | typedef bool (chunk_commit_t)(void *, size_t, size_t, size_t, unsigned); 20 | 21 | /* 22 | * bool 23 | * chunk_decommit(void *chunk, size_t size, size_t offset, size_t length, 24 | * unsigned arena_ind); 25 | */ 26 | typedef bool (chunk_decommit_t)(void *, size_t, size_t, size_t, unsigned); 27 | 28 | /* 29 | * bool 30 | * chunk_purge(void *chunk, size_t size, size_t offset, size_t length, 31 | * unsigned arena_ind); 32 | */ 33 | typedef bool (chunk_purge_t)(void *, size_t, size_t, size_t, unsigned); 34 | 35 | /* 36 | * bool 37 | * chunk_split(void *chunk, size_t size, size_t size_a, size_t size_b, 38 | * bool committed, unsigned arena_ind); 39 | */ 40 | typedef bool (chunk_split_t)(void *, size_t, size_t, size_t, bool, unsigned); 41 | 42 | /* 43 | * bool 44 | * chunk_merge(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b, 45 | * bool committed, unsigned arena_ind); 46 | */ 47 | typedef bool (chunk_merge_t)(void *, size_t, void *, size_t, bool, unsigned); 48 | 49 | typedef struct { 50 | chunk_alloc_t *alloc; 51 | chunk_dalloc_t *dalloc; 52 | chunk_commit_t *commit; 53 | chunk_decommit_t *decommit; 54 | chunk_purge_t *purge; 55 | chunk_split_t *split; 56 | chunk_merge_t *merge; 57 | } chunk_hooks_t; 58 | -------------------------------------------------------------------------------- /bin/jemalloc-config.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | usage() { 4 | cat < 7 | Options: 8 | --help | -h : Print usage. 9 | --version : Print jemalloc version. 10 | --revision : Print shared library revision number. 11 | --config : Print configure options used to build jemalloc. 12 | --prefix : Print installation directory prefix. 13 | --bindir : Print binary installation directory. 14 | --datadir : Print data installation directory. 15 | --includedir : Print include installation directory. 16 | --libdir : Print library installation directory. 17 | --mandir : Print manual page installation directory. 18 | --cc : Print compiler used to build jemalloc. 19 | --cflags : Print compiler flags used to build jemalloc. 20 | --cppflags : Print preprocessor flags used to build jemalloc. 21 | --ldflags : Print library flags used to build jemalloc. 22 | --libs : Print libraries jemalloc was linked against. 23 | EOF 24 | } 25 | 26 | prefix="@prefix@" 27 | exec_prefix="@exec_prefix@" 28 | 29 | case "$1" in 30 | --help | -h) 31 | usage 32 | exit 0 33 | ;; 34 | --version) 35 | echo "@jemalloc_version@" 36 | ;; 37 | --revision) 38 | echo "@rev@" 39 | ;; 40 | --config) 41 | echo "@CONFIG@" 42 | ;; 43 | --prefix) 44 | echo "@PREFIX@" 45 | ;; 46 | --bindir) 47 | echo "@BINDIR@" 48 | ;; 49 | --datadir) 50 | echo "@DATADIR@" 51 | ;; 52 | --includedir) 53 | echo "@INCLUDEDIR@" 54 | ;; 55 | --libdir) 56 | echo "@LIBDIR@" 57 | ;; 58 | --mandir) 59 | echo "@MANDIR@" 60 | ;; 61 | --cc) 62 | echo "@CC@" 63 | ;; 64 | --cflags) 65 | echo "@CFLAGS@" 66 | ;; 67 | --cppflags) 68 | echo "@CPPFLAGS@" 69 | ;; 70 | --ldflags) 71 | echo "@LDFLAGS@ @EXTRA_LDFLAGS@" 72 | ;; 73 | --libs) 74 | echo "@LIBS@" 75 | ;; 76 | *) 77 | usage 78 | exit 1 79 | esac 80 | -------------------------------------------------------------------------------- /include/jemalloc/internal/quarantine.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | typedef struct quarantine_obj_s quarantine_obj_t; 5 | typedef struct quarantine_s quarantine_t; 6 | 7 | /* Default per thread quarantine size if valgrind is enabled. */ 8 | #define JEMALLOC_VALGRIND_QUARANTINE_DEFAULT (ZU(1) << 24) 9 | 10 | #endif /* JEMALLOC_H_TYPES */ 11 | /******************************************************************************/ 12 | #ifdef JEMALLOC_H_STRUCTS 13 | 14 | struct quarantine_obj_s { 15 | void *ptr; 16 | size_t usize; 17 | }; 18 | 19 | struct quarantine_s { 20 | size_t curbytes; 21 | size_t curobjs; 22 | size_t first; 23 | #define LG_MAXOBJS_INIT 10 24 | size_t lg_maxobjs; 25 | quarantine_obj_t objs[1]; /* Dynamically sized ring buffer. */ 26 | }; 27 | 28 | #endif /* JEMALLOC_H_STRUCTS */ 29 | /******************************************************************************/ 30 | #ifdef JEMALLOC_H_EXTERNS 31 | 32 | void quarantine_alloc_hook_work(tsd_t *tsd); 33 | void quarantine(tsd_t *tsd, void *ptr); 34 | void quarantine_cleanup(tsd_t *tsd); 35 | 36 | #endif /* JEMALLOC_H_EXTERNS */ 37 | /******************************************************************************/ 38 | #ifdef JEMALLOC_H_INLINES 39 | 40 | #ifndef JEMALLOC_ENABLE_INLINE 41 | void quarantine_alloc_hook(void); 42 | #endif 43 | 44 | #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_QUARANTINE_C_)) 45 | JEMALLOC_ALWAYS_INLINE void 46 | quarantine_alloc_hook(void) 47 | { 48 | tsd_t *tsd; 49 | 50 | assert(config_fill && opt_quarantine); 51 | 52 | tsd = tsd_fetch(); 53 | if (tsd_quarantine_get(tsd) == NULL) 54 | quarantine_alloc_hook_work(tsd); 55 | } 56 | #endif 57 | 58 | #endif /* JEMALLOC_H_INLINES */ 59 | /******************************************************************************/ 60 | 61 | -------------------------------------------------------------------------------- /test/unit/zero.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #ifdef JEMALLOC_FILL 4 | const char *malloc_conf = 5 | "abort:false,junk:false,zero:true,redzone:false,quarantine:0"; 6 | #endif 7 | 8 | static void 9 | test_zero(size_t sz_min, size_t sz_max) 10 | { 11 | uint8_t *s; 12 | size_t sz_prev, sz, i; 13 | #define MAGIC ((uint8_t)0x61) 14 | 15 | sz_prev = 0; 16 | s = (uint8_t *)mallocx(sz_min, 0); 17 | assert_ptr_not_null((void *)s, "Unexpected mallocx() failure"); 18 | 19 | for (sz = sallocx(s, 0); sz <= sz_max; 20 | sz_prev = sz, sz = sallocx(s, 0)) { 21 | if (sz_prev > 0) { 22 | assert_u_eq(s[0], MAGIC, 23 | "Previously allocated byte %zu/%zu is corrupted", 24 | ZU(0), sz_prev); 25 | assert_u_eq(s[sz_prev-1], MAGIC, 26 | "Previously allocated byte %zu/%zu is corrupted", 27 | sz_prev-1, sz_prev); 28 | } 29 | 30 | for (i = sz_prev; i < sz; i++) { 31 | assert_u_eq(s[i], 0x0, 32 | "Newly allocated byte %zu/%zu isn't zero-filled", 33 | i, sz); 34 | s[i] = MAGIC; 35 | } 36 | 37 | if (xallocx(s, sz+1, 0, 0) == sz) { 38 | s = (uint8_t *)rallocx(s, sz+1, 0); 39 | assert_ptr_not_null((void *)s, 40 | "Unexpected rallocx() failure"); 41 | } 42 | } 43 | 44 | dallocx(s, 0); 45 | #undef MAGIC 46 | } 47 | 48 | TEST_BEGIN(test_zero_small) 49 | { 50 | 51 | test_skip_if(!config_fill); 52 | test_zero(1, SMALL_MAXCLASS-1); 53 | } 54 | TEST_END 55 | 56 | TEST_BEGIN(test_zero_large) 57 | { 58 | 59 | test_skip_if(!config_fill); 60 | test_zero(SMALL_MAXCLASS+1, large_maxclass); 61 | } 62 | TEST_END 63 | 64 | TEST_BEGIN(test_zero_huge) 65 | { 66 | 67 | test_skip_if(!config_fill); 68 | test_zero(large_maxclass+1, chunksize*2); 69 | } 70 | TEST_END 71 | 72 | int 73 | main(void) 74 | { 75 | 76 | return (test( 77 | test_zero_small, 78 | test_zero_large, 79 | test_zero_huge)); 80 | } 81 | -------------------------------------------------------------------------------- /test/integration/thread_arena.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define NTHREADS 10 4 | 5 | void * 6 | thd_start(void *arg) 7 | { 8 | unsigned main_arena_ind = *(unsigned *)arg; 9 | void *p; 10 | unsigned arena_ind; 11 | size_t size; 12 | int err; 13 | 14 | p = malloc(1); 15 | assert_ptr_not_null(p, "Error in malloc()"); 16 | free(p); 17 | 18 | size = sizeof(arena_ind); 19 | if ((err = mallctl("thread.arena", &arena_ind, &size, &main_arena_ind, 20 | sizeof(main_arena_ind)))) { 21 | char buf[BUFERROR_BUF]; 22 | 23 | buferror(err, buf, sizeof(buf)); 24 | test_fail("Error in mallctl(): %s", buf); 25 | } 26 | 27 | size = sizeof(arena_ind); 28 | if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) { 29 | char buf[BUFERROR_BUF]; 30 | 31 | buferror(err, buf, sizeof(buf)); 32 | test_fail("Error in mallctl(): %s", buf); 33 | } 34 | assert_u_eq(arena_ind, main_arena_ind, 35 | "Arena index should be same as for main thread"); 36 | 37 | return (NULL); 38 | } 39 | 40 | TEST_BEGIN(test_thread_arena) 41 | { 42 | void *p; 43 | unsigned arena_ind; 44 | size_t size; 45 | int err; 46 | thd_t thds[NTHREADS]; 47 | unsigned i; 48 | 49 | p = malloc(1); 50 | assert_ptr_not_null(p, "Error in malloc()"); 51 | 52 | size = sizeof(arena_ind); 53 | if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) { 54 | char buf[BUFERROR_BUF]; 55 | 56 | buferror(err, buf, sizeof(buf)); 57 | test_fail("Error in mallctl(): %s", buf); 58 | } 59 | 60 | for (i = 0; i < NTHREADS; i++) { 61 | thd_create(&thds[i], thd_start, 62 | (void *)&arena_ind); 63 | } 64 | 65 | for (i = 0; i < NTHREADS; i++) { 66 | intptr_t join_ret; 67 | thd_join(thds[i], (void *)&join_ret); 68 | assert_zd_eq(join_ret, 0, "Unexpected thread join error"); 69 | } 70 | } 71 | TEST_END 72 | 73 | int 74 | main(void) 75 | { 76 | 77 | return (test( 78 | test_thread_arena)); 79 | } 80 | -------------------------------------------------------------------------------- /include/jemalloc/internal/jemalloc_internal_macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * JEMALLOC_ALWAYS_INLINE and JEMALLOC_INLINE are used within header files for 3 | * functions that are static inline functions if inlining is enabled, and 4 | * single-definition library-private functions if inlining is disabled. 5 | * 6 | * JEMALLOC_ALWAYS_INLINE_C and JEMALLOC_INLINE_C are for use in .c files, in 7 | * which case the denoted functions are always static, regardless of whether 8 | * inlining is enabled. 9 | */ 10 | #if defined(JEMALLOC_DEBUG) || defined(JEMALLOC_CODE_COVERAGE) 11 | /* Disable inlining to make debugging/profiling easier. */ 12 | # define JEMALLOC_ALWAYS_INLINE 13 | # define JEMALLOC_ALWAYS_INLINE_C static 14 | # define JEMALLOC_INLINE 15 | # define JEMALLOC_INLINE_C static 16 | # define inline 17 | #else 18 | # define JEMALLOC_ENABLE_INLINE 19 | # ifdef JEMALLOC_HAVE_ATTR 20 | # define JEMALLOC_ALWAYS_INLINE \ 21 | static inline JEMALLOC_ATTR(unused) JEMALLOC_ATTR(always_inline) 22 | # define JEMALLOC_ALWAYS_INLINE_C \ 23 | static inline JEMALLOC_ATTR(always_inline) 24 | # else 25 | # define JEMALLOC_ALWAYS_INLINE static inline 26 | # define JEMALLOC_ALWAYS_INLINE_C static inline 27 | # endif 28 | # define JEMALLOC_INLINE static inline 29 | # define JEMALLOC_INLINE_C static inline 30 | # ifdef _MSC_VER 31 | # define inline _inline 32 | # endif 33 | #endif 34 | 35 | #ifdef JEMALLOC_CC_SILENCE 36 | # define UNUSED JEMALLOC_ATTR(unused) 37 | #else 38 | # define UNUSED 39 | #endif 40 | 41 | #define ZU(z) ((size_t)z) 42 | #define ZI(z) ((ssize_t)z) 43 | #define QU(q) ((uint64_t)q) 44 | #define QI(q) ((int64_t)q) 45 | 46 | #define KZU(z) ZU(z##ULL) 47 | #define KZI(z) ZI(z##LL) 48 | #define KQU(q) QU(q##ULL) 49 | #define KQI(q) QI(q##LL) 50 | 51 | #ifndef __DECONST 52 | # define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) 53 | #endif 54 | 55 | #ifndef JEMALLOC_HAS_RESTRICT 56 | # define restrict 57 | #endif 58 | -------------------------------------------------------------------------------- /include/jemalloc/internal/nstime.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | typedef struct nstime_s nstime_t; 5 | 6 | /* Maximum supported number of seconds (~584 years). */ 7 | #define NSTIME_SEC_MAX KQU(18446744072) 8 | 9 | #endif /* JEMALLOC_H_TYPES */ 10 | /******************************************************************************/ 11 | #ifdef JEMALLOC_H_STRUCTS 12 | 13 | struct nstime_s { 14 | uint64_t ns; 15 | }; 16 | 17 | #endif /* JEMALLOC_H_STRUCTS */ 18 | /******************************************************************************/ 19 | #ifdef JEMALLOC_H_EXTERNS 20 | 21 | void nstime_init(nstime_t *time, uint64_t ns); 22 | void nstime_init2(nstime_t *time, uint64_t sec, uint64_t nsec); 23 | uint64_t nstime_ns(const nstime_t *time); 24 | uint64_t nstime_sec(const nstime_t *time); 25 | uint64_t nstime_nsec(const nstime_t *time); 26 | void nstime_copy(nstime_t *time, const nstime_t *source); 27 | int nstime_compare(const nstime_t *a, const nstime_t *b); 28 | void nstime_add(nstime_t *time, const nstime_t *addend); 29 | void nstime_subtract(nstime_t *time, const nstime_t *subtrahend); 30 | void nstime_imultiply(nstime_t *time, uint64_t multiplier); 31 | void nstime_idivide(nstime_t *time, uint64_t divisor); 32 | uint64_t nstime_divide(const nstime_t *time, const nstime_t *divisor); 33 | #ifdef JEMALLOC_JET 34 | typedef bool (nstime_monotonic_t)(void); 35 | extern nstime_monotonic_t *nstime_monotonic; 36 | typedef bool (nstime_update_t)(nstime_t *); 37 | extern nstime_update_t *nstime_update; 38 | #else 39 | bool nstime_monotonic(void); 40 | bool nstime_update(nstime_t *time); 41 | #endif 42 | 43 | #endif /* JEMALLOC_H_EXTERNS */ 44 | /******************************************************************************/ 45 | #ifdef JEMALLOC_H_INLINES 46 | 47 | #endif /* JEMALLOC_H_INLINES */ 48 | /******************************************************************************/ 49 | -------------------------------------------------------------------------------- /include/jemalloc/internal/ticker.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | typedef struct ticker_s ticker_t; 5 | 6 | #endif /* JEMALLOC_H_TYPES */ 7 | /******************************************************************************/ 8 | #ifdef JEMALLOC_H_STRUCTS 9 | 10 | struct ticker_s { 11 | int32_t tick; 12 | int32_t nticks; 13 | }; 14 | 15 | #endif /* JEMALLOC_H_STRUCTS */ 16 | /******************************************************************************/ 17 | #ifdef JEMALLOC_H_EXTERNS 18 | 19 | #endif /* JEMALLOC_H_EXTERNS */ 20 | /******************************************************************************/ 21 | #ifdef JEMALLOC_H_INLINES 22 | 23 | #ifndef JEMALLOC_ENABLE_INLINE 24 | void ticker_init(ticker_t *ticker, int32_t nticks); 25 | void ticker_copy(ticker_t *ticker, const ticker_t *other); 26 | int32_t ticker_read(const ticker_t *ticker); 27 | bool ticker_ticks(ticker_t *ticker, int32_t nticks); 28 | bool ticker_tick(ticker_t *ticker); 29 | #endif 30 | 31 | #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TICKER_C_)) 32 | JEMALLOC_INLINE void 33 | ticker_init(ticker_t *ticker, int32_t nticks) 34 | { 35 | 36 | ticker->tick = nticks; 37 | ticker->nticks = nticks; 38 | } 39 | 40 | JEMALLOC_INLINE void 41 | ticker_copy(ticker_t *ticker, const ticker_t *other) 42 | { 43 | 44 | *ticker = *other; 45 | } 46 | 47 | JEMALLOC_INLINE int32_t 48 | ticker_read(const ticker_t *ticker) 49 | { 50 | 51 | return (ticker->tick); 52 | } 53 | 54 | JEMALLOC_INLINE bool 55 | ticker_ticks(ticker_t *ticker, int32_t nticks) 56 | { 57 | 58 | if (unlikely(ticker->tick < nticks)) { 59 | ticker->tick = ticker->nticks; 60 | return (true); 61 | } 62 | ticker->tick -= nticks; 63 | return(false); 64 | } 65 | 66 | JEMALLOC_INLINE bool 67 | ticker_tick(ticker_t *ticker) 68 | { 69 | 70 | return (ticker_ticks(ticker, 1)); 71 | } 72 | #endif 73 | 74 | #endif /* JEMALLOC_H_INLINES */ 75 | /******************************************************************************/ 76 | -------------------------------------------------------------------------------- /include/jemalloc/internal/jemalloc_internal_decls.h: -------------------------------------------------------------------------------- 1 | #ifndef JEMALLOC_INTERNAL_DECLS_H 2 | #define JEMALLOC_INTERNAL_DECLS_H 3 | 4 | #include 5 | #ifdef _WIN32 6 | # include 7 | # include "msvc_compat/windows_extra.h" 8 | 9 | # ifdef _MSC_VER 10 | # include 11 | # define getpid _getpid 12 | # endif 13 | 14 | #else 15 | # include 16 | # include 17 | # if !defined(__pnacl__) && !defined(__native_client__) 18 | # include 19 | # if !defined(SYS_write) && defined(__NR_write) 20 | # define SYS_write __NR_write 21 | # endif 22 | # include 23 | # endif 24 | # include 25 | # ifdef JEMALLOC_OS_UNFAIR_LOCK 26 | # include 27 | # endif 28 | # ifdef JEMALLOC_GLIBC_MALLOC_HOOK 29 | # include 30 | # endif 31 | # include 32 | # include 33 | # include 34 | # ifdef JEMALLOC_HAVE_MACH_ABSOLUTE_TIME 35 | # include 36 | # endif 37 | #endif 38 | #include 39 | 40 | #include 41 | #ifndef SIZE_T_MAX 42 | # define SIZE_T_MAX SIZE_MAX 43 | #endif 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #ifndef offsetof 51 | # define offsetof(type, member) ((size_t)&(((type *)NULL)->member)) 52 | #endif 53 | #include 54 | #include 55 | #include 56 | #ifdef _MSC_VER 57 | # include 58 | typedef intptr_t ssize_t; 59 | # define PATH_MAX 1024 60 | # define STDERR_FILENO 2 61 | # define __func__ __FUNCTION__ 62 | # ifdef JEMALLOC_HAS_RESTRICT 63 | # define restrict __restrict 64 | # endif 65 | /* Disable warnings about deprecated system functions. */ 66 | # pragma warning(disable: 4996) 67 | #if _MSC_VER < 1800 68 | static int 69 | isblank(int c) 70 | { 71 | 72 | return (c == '\t' || c == ' '); 73 | } 74 | #endif 75 | #else 76 | # include 77 | #endif 78 | #include 79 | 80 | #endif /* JEMALLOC_INTERNAL_H */ 81 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /*.gcov.* 2 | 3 | /bin/jemalloc-config 4 | /bin/jemalloc.sh 5 | /bin/jeprof 6 | 7 | /config.stamp 8 | /config.log 9 | /config.status 10 | /configure 11 | 12 | /doc/html.xsl 13 | /doc/manpages.xsl 14 | /doc/jemalloc.xml 15 | /doc/jemalloc.html 16 | /doc/jemalloc.3 17 | 18 | /jemalloc.pc 19 | 20 | /lib/ 21 | 22 | /Makefile 23 | 24 | /include/jemalloc/internal/jemalloc_internal.h 25 | /include/jemalloc/internal/jemalloc_internal_defs.h 26 | /include/jemalloc/internal/private_namespace.h 27 | /include/jemalloc/internal/private_unnamespace.h 28 | /include/jemalloc/internal/public_namespace.h 29 | /include/jemalloc/internal/public_symbols.txt 30 | /include/jemalloc/internal/public_unnamespace.h 31 | /include/jemalloc/internal/size_classes.h 32 | /include/jemalloc/jemalloc.h 33 | /include/jemalloc/jemalloc_defs.h 34 | /include/jemalloc/jemalloc_macros.h 35 | /include/jemalloc/jemalloc_mangle.h 36 | /include/jemalloc/jemalloc_mangle_jet.h 37 | /include/jemalloc/jemalloc_protos.h 38 | /include/jemalloc/jemalloc_protos_jet.h 39 | /include/jemalloc/jemalloc_rename.h 40 | /include/jemalloc/jemalloc_typedefs.h 41 | 42 | /src/*.[od] 43 | /src/*.gcda 44 | /src/*.gcno 45 | 46 | /test/test.sh 47 | test/include/test/jemalloc_test.h 48 | test/include/test/jemalloc_test_defs.h 49 | 50 | /test/integration/[A-Za-z]* 51 | !/test/integration/[A-Za-z]*.* 52 | /test/integration/*.[od] 53 | /test/integration/*.gcda 54 | /test/integration/*.gcno 55 | /test/integration/*.out 56 | 57 | /test/src/*.[od] 58 | /test/src/*.gcda 59 | /test/src/*.gcno 60 | 61 | /test/stress/[A-Za-z]* 62 | !/test/stress/[A-Za-z]*.* 63 | /test/stress/*.[od] 64 | /test/stress/*.gcda 65 | /test/stress/*.gcno 66 | /test/stress/*.out 67 | 68 | /test/unit/[A-Za-z]* 69 | !/test/unit/[A-Za-z]*.* 70 | /test/unit/*.[od] 71 | /test/unit/*.gcda 72 | /test/unit/*.gcno 73 | /test/unit/*.out 74 | 75 | /VERSION 76 | 77 | *.pdb 78 | *.sdf 79 | *.opendb 80 | *.opensdf 81 | *.cachefile 82 | *.suo 83 | *.user 84 | *.sln.docstates 85 | *.tmp 86 | /msvc/Win32/ 87 | /msvc/x64/ 88 | /msvc/projects/*/*/Debug*/ 89 | /msvc/projects/*/*/Release*/ 90 | /msvc/projects/*/*/Win32/ 91 | /msvc/projects/*/*/x64/ 92 | /build/ -------------------------------------------------------------------------------- /test/unit/mq.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define NSENDERS 3 4 | #define NMSGS 100000 5 | 6 | typedef struct mq_msg_s mq_msg_t; 7 | struct mq_msg_s { 8 | mq_msg(mq_msg_t) link; 9 | }; 10 | mq_gen(static, mq_, mq_t, mq_msg_t, link) 11 | 12 | TEST_BEGIN(test_mq_basic) 13 | { 14 | mq_t mq; 15 | mq_msg_t msg; 16 | 17 | assert_false(mq_init(&mq), "Unexpected mq_init() failure"); 18 | assert_u_eq(mq_count(&mq), 0, "mq should be empty"); 19 | assert_ptr_null(mq_tryget(&mq), 20 | "mq_tryget() should fail when the queue is empty"); 21 | 22 | mq_put(&mq, &msg); 23 | assert_u_eq(mq_count(&mq), 1, "mq should contain one message"); 24 | assert_ptr_eq(mq_tryget(&mq), &msg, "mq_tryget() should return msg"); 25 | 26 | mq_put(&mq, &msg); 27 | assert_ptr_eq(mq_get(&mq), &msg, "mq_get() should return msg"); 28 | 29 | mq_fini(&mq); 30 | } 31 | TEST_END 32 | 33 | static void * 34 | thd_receiver_start(void *arg) 35 | { 36 | mq_t *mq = (mq_t *)arg; 37 | unsigned i; 38 | 39 | for (i = 0; i < (NSENDERS * NMSGS); i++) { 40 | mq_msg_t *msg = mq_get(mq); 41 | assert_ptr_not_null(msg, "mq_get() should never return NULL"); 42 | dallocx(msg, 0); 43 | } 44 | return (NULL); 45 | } 46 | 47 | static void * 48 | thd_sender_start(void *arg) 49 | { 50 | mq_t *mq = (mq_t *)arg; 51 | unsigned i; 52 | 53 | for (i = 0; i < NMSGS; i++) { 54 | mq_msg_t *msg; 55 | void *p; 56 | p = mallocx(sizeof(mq_msg_t), 0); 57 | assert_ptr_not_null(p, "Unexpected mallocx() failure"); 58 | msg = (mq_msg_t *)p; 59 | mq_put(mq, msg); 60 | } 61 | return (NULL); 62 | } 63 | 64 | TEST_BEGIN(test_mq_threaded) 65 | { 66 | mq_t mq; 67 | thd_t receiver; 68 | thd_t senders[NSENDERS]; 69 | unsigned i; 70 | 71 | assert_false(mq_init(&mq), "Unexpected mq_init() failure"); 72 | 73 | thd_create(&receiver, thd_receiver_start, (void *)&mq); 74 | for (i = 0; i < NSENDERS; i++) 75 | thd_create(&senders[i], thd_sender_start, (void *)&mq); 76 | 77 | thd_join(receiver, NULL); 78 | for (i = 0; i < NSENDERS; i++) 79 | thd_join(senders[i], NULL); 80 | 81 | mq_fini(&mq); 82 | } 83 | TEST_END 84 | 85 | int 86 | main(void) 87 | { 88 | 89 | return (test( 90 | test_mq_basic, 91 | test_mq_threaded)); 92 | } 93 | 94 | -------------------------------------------------------------------------------- /test/unit/prof_accum.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define NTHREADS 4 4 | #define NALLOCS_PER_THREAD 50 5 | #define DUMP_INTERVAL 1 6 | #define BT_COUNT_CHECK_INTERVAL 5 7 | 8 | #ifdef JEMALLOC_PROF 9 | const char *malloc_conf = 10 | "prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0"; 11 | #endif 12 | 13 | static int 14 | prof_dump_open_intercept(bool propagate_err, const char *filename) 15 | { 16 | int fd; 17 | 18 | fd = open("/dev/null", O_WRONLY); 19 | assert_d_ne(fd, -1, "Unexpected open() failure"); 20 | 21 | return (fd); 22 | } 23 | 24 | static void * 25 | alloc_from_permuted_backtrace(unsigned thd_ind, unsigned iteration) 26 | { 27 | 28 | return (btalloc(1, thd_ind*NALLOCS_PER_THREAD + iteration)); 29 | } 30 | 31 | static void * 32 | thd_start(void *varg) 33 | { 34 | unsigned thd_ind = *(unsigned *)varg; 35 | size_t bt_count_prev, bt_count; 36 | unsigned i_prev, i; 37 | 38 | i_prev = 0; 39 | bt_count_prev = 0; 40 | for (i = 0; i < NALLOCS_PER_THREAD; i++) { 41 | void *p = alloc_from_permuted_backtrace(thd_ind, i); 42 | dallocx(p, 0); 43 | if (i % DUMP_INTERVAL == 0) { 44 | assert_d_eq(mallctl("prof.dump", NULL, NULL, NULL, 0), 45 | 0, "Unexpected error while dumping heap profile"); 46 | } 47 | 48 | if (i % BT_COUNT_CHECK_INTERVAL == 0 || 49 | i+1 == NALLOCS_PER_THREAD) { 50 | bt_count = prof_bt_count(); 51 | assert_zu_le(bt_count_prev+(i-i_prev), bt_count, 52 | "Expected larger backtrace count increase"); 53 | i_prev = i; 54 | bt_count_prev = bt_count; 55 | } 56 | } 57 | 58 | return (NULL); 59 | } 60 | 61 | TEST_BEGIN(test_idump) 62 | { 63 | bool active; 64 | thd_t thds[NTHREADS]; 65 | unsigned thd_args[NTHREADS]; 66 | unsigned i; 67 | 68 | test_skip_if(!config_prof); 69 | 70 | active = true; 71 | assert_d_eq(mallctl("prof.active", NULL, NULL, &active, sizeof(active)), 72 | 0, "Unexpected mallctl failure while activating profiling"); 73 | 74 | prof_dump_open = prof_dump_open_intercept; 75 | 76 | for (i = 0; i < NTHREADS; i++) { 77 | thd_args[i] = i; 78 | thd_create(&thds[i], thd_start, (void *)&thd_args[i]); 79 | } 80 | for (i = 0; i < NTHREADS; i++) 81 | thd_join(thds[i], NULL); 82 | } 83 | TEST_END 84 | 85 | int 86 | main(void) 87 | { 88 | 89 | return (test( 90 | test_idump)); 91 | } 92 | -------------------------------------------------------------------------------- /test/unit/prof_gdump.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #ifdef JEMALLOC_PROF 4 | const char *malloc_conf = "prof:true,prof_active:false,prof_gdump:true"; 5 | #endif 6 | 7 | static bool did_prof_dump_open; 8 | 9 | static int 10 | prof_dump_open_intercept(bool propagate_err, const char *filename) 11 | { 12 | int fd; 13 | 14 | did_prof_dump_open = true; 15 | 16 | fd = open("/dev/null", O_WRONLY); 17 | assert_d_ne(fd, -1, "Unexpected open() failure"); 18 | 19 | return (fd); 20 | } 21 | 22 | TEST_BEGIN(test_gdump) 23 | { 24 | bool active, gdump, gdump_old; 25 | void *p, *q, *r, *s; 26 | size_t sz; 27 | 28 | test_skip_if(!config_prof); 29 | 30 | active = true; 31 | assert_d_eq(mallctl("prof.active", NULL, NULL, &active, sizeof(active)), 32 | 0, "Unexpected mallctl failure while activating profiling"); 33 | 34 | prof_dump_open = prof_dump_open_intercept; 35 | 36 | did_prof_dump_open = false; 37 | p = mallocx(chunksize, 0); 38 | assert_ptr_not_null(p, "Unexpected mallocx() failure"); 39 | assert_true(did_prof_dump_open, "Expected a profile dump"); 40 | 41 | did_prof_dump_open = false; 42 | q = mallocx(chunksize, 0); 43 | assert_ptr_not_null(q, "Unexpected mallocx() failure"); 44 | assert_true(did_prof_dump_open, "Expected a profile dump"); 45 | 46 | gdump = false; 47 | sz = sizeof(gdump_old); 48 | assert_d_eq(mallctl("prof.gdump", &gdump_old, &sz, &gdump, 49 | sizeof(gdump)), 0, 50 | "Unexpected mallctl failure while disabling prof.gdump"); 51 | assert(gdump_old); 52 | did_prof_dump_open = false; 53 | r = mallocx(chunksize, 0); 54 | assert_ptr_not_null(q, "Unexpected mallocx() failure"); 55 | assert_false(did_prof_dump_open, "Unexpected profile dump"); 56 | 57 | gdump = true; 58 | sz = sizeof(gdump_old); 59 | assert_d_eq(mallctl("prof.gdump", &gdump_old, &sz, &gdump, 60 | sizeof(gdump)), 0, 61 | "Unexpected mallctl failure while enabling prof.gdump"); 62 | assert(!gdump_old); 63 | did_prof_dump_open = false; 64 | s = mallocx(chunksize, 0); 65 | assert_ptr_not_null(q, "Unexpected mallocx() failure"); 66 | assert_true(did_prof_dump_open, "Expected a profile dump"); 67 | 68 | dallocx(p, 0); 69 | dallocx(q, 0); 70 | dallocx(r, 0); 71 | dallocx(s, 0); 72 | } 73 | TEST_END 74 | 75 | int 76 | main(void) 77 | { 78 | 79 | return (test( 80 | test_gdump)); 81 | } 82 | -------------------------------------------------------------------------------- /src/chunk_mmap.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_CHUNK_MMAP_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | /******************************************************************************/ 5 | 6 | static void * 7 | chunk_alloc_mmap_slow(size_t size, size_t alignment, bool *zero, bool *commit) 8 | { 9 | void *ret; 10 | size_t alloc_size; 11 | 12 | alloc_size = size + alignment - PAGE; 13 | /* Beware size_t wrap-around. */ 14 | if (alloc_size < size) 15 | return (NULL); 16 | do { 17 | void *pages; 18 | size_t leadsize; 19 | pages = pages_map(NULL, alloc_size, commit); 20 | if (pages == NULL) 21 | return (NULL); 22 | leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) - 23 | (uintptr_t)pages; 24 | ret = pages_trim(pages, alloc_size, leadsize, size, commit); 25 | } while (ret == NULL); 26 | 27 | assert(ret != NULL); 28 | *zero = true; 29 | return (ret); 30 | } 31 | 32 | void * 33 | chunk_alloc_mmap(void *new_addr, size_t size, size_t alignment, bool *zero, 34 | bool *commit) 35 | { 36 | void *ret; 37 | size_t offset; 38 | 39 | /* 40 | * Ideally, there would be a way to specify alignment to mmap() (like 41 | * NetBSD has), but in the absence of such a feature, we have to work 42 | * hard to efficiently create aligned mappings. The reliable, but 43 | * slow method is to create a mapping that is over-sized, then trim the 44 | * excess. However, that always results in one or two calls to 45 | * pages_unmap(). 46 | * 47 | * Optimistically try mapping precisely the right amount before falling 48 | * back to the slow method, with the expectation that the optimistic 49 | * approach works most of the time. 50 | */ 51 | 52 | assert(alignment != 0); 53 | assert((alignment & chunksize_mask) == 0); 54 | 55 | ret = pages_map(new_addr, size, commit); 56 | if (ret == NULL || ret == new_addr) 57 | return (ret); 58 | assert(new_addr == NULL); 59 | offset = ALIGNMENT_ADDR2OFFSET(ret, alignment); 60 | if (offset != 0) { 61 | pages_unmap(ret, size); 62 | return (chunk_alloc_mmap_slow(size, alignment, zero, commit)); 63 | } 64 | 65 | assert(ret != NULL); 66 | *zero = true; 67 | return (ret); 68 | } 69 | 70 | bool 71 | chunk_dalloc_mmap(void *chunk, size_t size) 72 | { 73 | 74 | if (config_munmap) 75 | pages_unmap(chunk, size); 76 | 77 | return (!config_munmap); 78 | } 79 | -------------------------------------------------------------------------------- /test/unit/ticker.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | TEST_BEGIN(test_ticker_tick) 4 | { 5 | #define NREPS 2 6 | #define NTICKS 3 7 | ticker_t ticker; 8 | int32_t i, j; 9 | 10 | ticker_init(&ticker, NTICKS); 11 | for (i = 0; i < NREPS; i++) { 12 | for (j = 0; j < NTICKS; j++) { 13 | assert_u_eq(ticker_read(&ticker), NTICKS - j, 14 | "Unexpected ticker value (i=%d, j=%d)", i, j); 15 | assert_false(ticker_tick(&ticker), 16 | "Unexpected ticker fire (i=%d, j=%d)", i, j); 17 | } 18 | assert_u32_eq(ticker_read(&ticker), 0, 19 | "Expected ticker depletion"); 20 | assert_true(ticker_tick(&ticker), 21 | "Expected ticker fire (i=%d)", i); 22 | assert_u32_eq(ticker_read(&ticker), NTICKS, 23 | "Expected ticker reset"); 24 | } 25 | #undef NTICKS 26 | } 27 | TEST_END 28 | 29 | TEST_BEGIN(test_ticker_ticks) 30 | { 31 | #define NTICKS 3 32 | ticker_t ticker; 33 | 34 | ticker_init(&ticker, NTICKS); 35 | 36 | assert_u_eq(ticker_read(&ticker), NTICKS, "Unexpected ticker value"); 37 | assert_false(ticker_ticks(&ticker, NTICKS), "Unexpected ticker fire"); 38 | assert_u_eq(ticker_read(&ticker), 0, "Unexpected ticker value"); 39 | assert_true(ticker_ticks(&ticker, NTICKS), "Expected ticker fire"); 40 | assert_u_eq(ticker_read(&ticker), NTICKS, "Unexpected ticker value"); 41 | 42 | assert_true(ticker_ticks(&ticker, NTICKS + 1), "Expected ticker fire"); 43 | assert_u_eq(ticker_read(&ticker), NTICKS, "Unexpected ticker value"); 44 | #undef NTICKS 45 | } 46 | TEST_END 47 | 48 | TEST_BEGIN(test_ticker_copy) 49 | { 50 | #define NTICKS 3 51 | ticker_t ta, tb; 52 | 53 | ticker_init(&ta, NTICKS); 54 | ticker_copy(&tb, &ta); 55 | assert_u_eq(ticker_read(&tb), NTICKS, "Unexpected ticker value"); 56 | assert_true(ticker_ticks(&tb, NTICKS + 1), "Expected ticker fire"); 57 | assert_u_eq(ticker_read(&tb), NTICKS, "Unexpected ticker value"); 58 | 59 | ticker_tick(&ta); 60 | ticker_copy(&tb, &ta); 61 | assert_u_eq(ticker_read(&tb), NTICKS - 1, "Unexpected ticker value"); 62 | assert_true(ticker_ticks(&tb, NTICKS), "Expected ticker fire"); 63 | assert_u_eq(ticker_read(&tb), NTICKS, "Unexpected ticker value"); 64 | #undef NTICKS 65 | } 66 | TEST_END 67 | 68 | int 69 | main(void) 70 | { 71 | 72 | return (test( 73 | test_ticker_tick, 74 | test_ticker_ticks, 75 | test_ticker_copy)); 76 | } 77 | -------------------------------------------------------------------------------- /include/jemalloc/internal/qr.h: -------------------------------------------------------------------------------- 1 | /* Ring definitions. */ 2 | #define qr(a_type) \ 3 | struct { \ 4 | a_type *qre_next; \ 5 | a_type *qre_prev; \ 6 | } 7 | 8 | /* Ring functions. */ 9 | #define qr_new(a_qr, a_field) do { \ 10 | (a_qr)->a_field.qre_next = (a_qr); \ 11 | (a_qr)->a_field.qre_prev = (a_qr); \ 12 | } while (0) 13 | 14 | #define qr_next(a_qr, a_field) ((a_qr)->a_field.qre_next) 15 | 16 | #define qr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev) 17 | 18 | #define qr_before_insert(a_qrelm, a_qr, a_field) do { \ 19 | (a_qr)->a_field.qre_prev = (a_qrelm)->a_field.qre_prev; \ 20 | (a_qr)->a_field.qre_next = (a_qrelm); \ 21 | (a_qr)->a_field.qre_prev->a_field.qre_next = (a_qr); \ 22 | (a_qrelm)->a_field.qre_prev = (a_qr); \ 23 | } while (0) 24 | 25 | #define qr_after_insert(a_qrelm, a_qr, a_field) \ 26 | do \ 27 | { \ 28 | (a_qr)->a_field.qre_next = (a_qrelm)->a_field.qre_next; \ 29 | (a_qr)->a_field.qre_prev = (a_qrelm); \ 30 | (a_qr)->a_field.qre_next->a_field.qre_prev = (a_qr); \ 31 | (a_qrelm)->a_field.qre_next = (a_qr); \ 32 | } while (0) 33 | 34 | #define qr_meld(a_qr_a, a_qr_b, a_field) do { \ 35 | void *t; \ 36 | (a_qr_a)->a_field.qre_prev->a_field.qre_next = (a_qr_b); \ 37 | (a_qr_b)->a_field.qre_prev->a_field.qre_next = (a_qr_a); \ 38 | t = (a_qr_a)->a_field.qre_prev; \ 39 | (a_qr_a)->a_field.qre_prev = (a_qr_b)->a_field.qre_prev; \ 40 | (a_qr_b)->a_field.qre_prev = t; \ 41 | } while (0) 42 | 43 | /* 44 | * qr_meld() and qr_split() are functionally equivalent, so there's no need to 45 | * have two copies of the code. 46 | */ 47 | #define qr_split(a_qr_a, a_qr_b, a_field) \ 48 | qr_meld((a_qr_a), (a_qr_b), a_field) 49 | 50 | #define qr_remove(a_qr, a_field) do { \ 51 | (a_qr)->a_field.qre_prev->a_field.qre_next \ 52 | = (a_qr)->a_field.qre_next; \ 53 | (a_qr)->a_field.qre_next->a_field.qre_prev \ 54 | = (a_qr)->a_field.qre_prev; \ 55 | (a_qr)->a_field.qre_next = (a_qr); \ 56 | (a_qr)->a_field.qre_prev = (a_qr); \ 57 | } while (0) 58 | 59 | #define qr_foreach(var, a_qr, a_field) \ 60 | for ((var) = (a_qr); \ 61 | (var) != NULL; \ 62 | (var) = (((var)->a_field.qre_next != (a_qr)) \ 63 | ? (var)->a_field.qre_next : NULL)) 64 | 65 | #define qr_reverse_foreach(var, a_qr, a_field) \ 66 | for ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL; \ 67 | (var) != NULL; \ 68 | (var) = (((var) != (a_qr)) \ 69 | ? (var)->a_field.qre_prev : NULL)) 70 | -------------------------------------------------------------------------------- /include/jemalloc/internal/ql.h: -------------------------------------------------------------------------------- 1 | /* List definitions. */ 2 | #define ql_head(a_type) \ 3 | struct { \ 4 | a_type *qlh_first; \ 5 | } 6 | 7 | #define ql_head_initializer(a_head) {NULL} 8 | 9 | #define ql_elm(a_type) qr(a_type) 10 | 11 | /* List functions. */ 12 | #define ql_new(a_head) do { \ 13 | (a_head)->qlh_first = NULL; \ 14 | } while (0) 15 | 16 | #define ql_elm_new(a_elm, a_field) qr_new((a_elm), a_field) 17 | 18 | #define ql_first(a_head) ((a_head)->qlh_first) 19 | 20 | #define ql_last(a_head, a_field) \ 21 | ((ql_first(a_head) != NULL) \ 22 | ? qr_prev(ql_first(a_head), a_field) : NULL) 23 | 24 | #define ql_next(a_head, a_elm, a_field) \ 25 | ((ql_last(a_head, a_field) != (a_elm)) \ 26 | ? qr_next((a_elm), a_field) : NULL) 27 | 28 | #define ql_prev(a_head, a_elm, a_field) \ 29 | ((ql_first(a_head) != (a_elm)) ? qr_prev((a_elm), a_field) \ 30 | : NULL) 31 | 32 | #define ql_before_insert(a_head, a_qlelm, a_elm, a_field) do { \ 33 | qr_before_insert((a_qlelm), (a_elm), a_field); \ 34 | if (ql_first(a_head) == (a_qlelm)) { \ 35 | ql_first(a_head) = (a_elm); \ 36 | } \ 37 | } while (0) 38 | 39 | #define ql_after_insert(a_qlelm, a_elm, a_field) \ 40 | qr_after_insert((a_qlelm), (a_elm), a_field) 41 | 42 | #define ql_head_insert(a_head, a_elm, a_field) do { \ 43 | if (ql_first(a_head) != NULL) { \ 44 | qr_before_insert(ql_first(a_head), (a_elm), a_field); \ 45 | } \ 46 | ql_first(a_head) = (a_elm); \ 47 | } while (0) 48 | 49 | #define ql_tail_insert(a_head, a_elm, a_field) do { \ 50 | if (ql_first(a_head) != NULL) { \ 51 | qr_before_insert(ql_first(a_head), (a_elm), a_field); \ 52 | } \ 53 | ql_first(a_head) = qr_next((a_elm), a_field); \ 54 | } while (0) 55 | 56 | #define ql_remove(a_head, a_elm, a_field) do { \ 57 | if (ql_first(a_head) == (a_elm)) { \ 58 | ql_first(a_head) = qr_next(ql_first(a_head), a_field); \ 59 | } \ 60 | if (ql_first(a_head) != (a_elm)) { \ 61 | qr_remove((a_elm), a_field); \ 62 | } else { \ 63 | ql_first(a_head) = NULL; \ 64 | } \ 65 | } while (0) 66 | 67 | #define ql_head_remove(a_head, a_type, a_field) do { \ 68 | a_type *t = ql_first(a_head); \ 69 | ql_remove((a_head), t, a_field); \ 70 | } while (0) 71 | 72 | #define ql_tail_remove(a_head, a_type, a_field) do { \ 73 | a_type *t = ql_last(a_head, a_field); \ 74 | ql_remove((a_head), t, a_field); \ 75 | } while (0) 76 | 77 | #define ql_foreach(a_var, a_head, a_field) \ 78 | qr_foreach((a_var), ql_first(a_head), a_field) 79 | 80 | #define ql_reverse_foreach(a_var, a_head, a_field) \ 81 | qr_reverse_foreach((a_var), ql_first(a_head), a_field) 82 | -------------------------------------------------------------------------------- /test/unit/tsd.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define THREAD_DATA 0x72b65c10 4 | 5 | typedef unsigned int data_t; 6 | 7 | static bool data_cleanup_executed; 8 | 9 | malloc_tsd_types(data_, data_t) 10 | malloc_tsd_protos(, data_, data_t) 11 | 12 | void 13 | data_cleanup(void *arg) 14 | { 15 | data_t *data = (data_t *)arg; 16 | 17 | if (!data_cleanup_executed) { 18 | assert_x_eq(*data, THREAD_DATA, 19 | "Argument passed into cleanup function should match tsd " 20 | "value"); 21 | } 22 | data_cleanup_executed = true; 23 | 24 | /* 25 | * Allocate during cleanup for two rounds, in order to assure that 26 | * jemalloc's internal tsd reinitialization happens. 27 | */ 28 | switch (*data) { 29 | case THREAD_DATA: 30 | *data = 1; 31 | data_tsd_set(data); 32 | break; 33 | case 1: 34 | *data = 2; 35 | data_tsd_set(data); 36 | break; 37 | case 2: 38 | return; 39 | default: 40 | not_reached(); 41 | } 42 | 43 | { 44 | void *p = mallocx(1, 0); 45 | assert_ptr_not_null(p, "Unexpeced mallocx() failure"); 46 | dallocx(p, 0); 47 | } 48 | } 49 | 50 | malloc_tsd_externs(data_, data_t) 51 | #define DATA_INIT 0x12345678 52 | malloc_tsd_data(, data_, data_t, DATA_INIT) 53 | malloc_tsd_funcs(, data_, data_t, DATA_INIT, data_cleanup) 54 | 55 | static void * 56 | thd_start(void *arg) 57 | { 58 | data_t d = (data_t)(uintptr_t)arg; 59 | void *p; 60 | 61 | assert_x_eq(*data_tsd_get(true), DATA_INIT, 62 | "Initial tsd get should return initialization value"); 63 | 64 | p = malloc(1); 65 | assert_ptr_not_null(p, "Unexpected malloc() failure"); 66 | 67 | data_tsd_set(&d); 68 | assert_x_eq(*data_tsd_get(true), d, 69 | "After tsd set, tsd get should return value that was set"); 70 | 71 | d = 0; 72 | assert_x_eq(*data_tsd_get(true), (data_t)(uintptr_t)arg, 73 | "Resetting local data should have no effect on tsd"); 74 | 75 | free(p); 76 | return (NULL); 77 | } 78 | 79 | TEST_BEGIN(test_tsd_main_thread) 80 | { 81 | 82 | thd_start((void *) 0xa5f3e329); 83 | } 84 | TEST_END 85 | 86 | TEST_BEGIN(test_tsd_sub_thread) 87 | { 88 | thd_t thd; 89 | 90 | data_cleanup_executed = false; 91 | thd_create(&thd, thd_start, (void *)THREAD_DATA); 92 | thd_join(thd, NULL); 93 | assert_true(data_cleanup_executed, 94 | "Cleanup function should have executed"); 95 | } 96 | TEST_END 97 | 98 | int 99 | main(void) 100 | { 101 | 102 | /* Core tsd bootstrapping must happen prior to data_tsd_boot(). */ 103 | if (nallocx(1, 0) == 0) { 104 | malloc_printf("Initialization error"); 105 | return (test_status_fail); 106 | } 107 | data_tsd_boot(); 108 | 109 | return (test( 110 | test_tsd_main_thread, 111 | test_tsd_sub_thread)); 112 | } 113 | -------------------------------------------------------------------------------- /include/jemalloc/internal/ckh.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | typedef struct ckh_s ckh_t; 5 | typedef struct ckhc_s ckhc_t; 6 | 7 | /* Typedefs to allow easy function pointer passing. */ 8 | typedef void ckh_hash_t (const void *, size_t[2]); 9 | typedef bool ckh_keycomp_t (const void *, const void *); 10 | 11 | /* Maintain counters used to get an idea of performance. */ 12 | /* #define CKH_COUNT */ 13 | /* Print counter values in ckh_delete() (requires CKH_COUNT). */ 14 | /* #define CKH_VERBOSE */ 15 | 16 | /* 17 | * There are 2^LG_CKH_BUCKET_CELLS cells in each hash table bucket. Try to fit 18 | * one bucket per L1 cache line. 19 | */ 20 | #define LG_CKH_BUCKET_CELLS (LG_CACHELINE - LG_SIZEOF_PTR - 1) 21 | 22 | #endif /* JEMALLOC_H_TYPES */ 23 | /******************************************************************************/ 24 | #ifdef JEMALLOC_H_STRUCTS 25 | 26 | /* Hash table cell. */ 27 | struct ckhc_s { 28 | const void *key; 29 | const void *data; 30 | }; 31 | 32 | struct ckh_s { 33 | #ifdef CKH_COUNT 34 | /* Counters used to get an idea of performance. */ 35 | uint64_t ngrows; 36 | uint64_t nshrinks; 37 | uint64_t nshrinkfails; 38 | uint64_t ninserts; 39 | uint64_t nrelocs; 40 | #endif 41 | 42 | /* Used for pseudo-random number generation. */ 43 | uint64_t prng_state; 44 | 45 | /* Total number of items. */ 46 | size_t count; 47 | 48 | /* 49 | * Minimum and current number of hash table buckets. There are 50 | * 2^LG_CKH_BUCKET_CELLS cells per bucket. 51 | */ 52 | unsigned lg_minbuckets; 53 | unsigned lg_curbuckets; 54 | 55 | /* Hash and comparison functions. */ 56 | ckh_hash_t *hash; 57 | ckh_keycomp_t *keycomp; 58 | 59 | /* Hash table with 2^lg_curbuckets buckets. */ 60 | ckhc_t *tab; 61 | }; 62 | 63 | #endif /* JEMALLOC_H_STRUCTS */ 64 | /******************************************************************************/ 65 | #ifdef JEMALLOC_H_EXTERNS 66 | 67 | bool ckh_new(tsd_t *tsd, ckh_t *ckh, size_t minitems, ckh_hash_t *hash, 68 | ckh_keycomp_t *keycomp); 69 | void ckh_delete(tsd_t *tsd, ckh_t *ckh); 70 | size_t ckh_count(ckh_t *ckh); 71 | bool ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data); 72 | bool ckh_insert(tsd_t *tsd, ckh_t *ckh, const void *key, const void *data); 73 | bool ckh_remove(tsd_t *tsd, ckh_t *ckh, const void *searchkey, void **key, 74 | void **data); 75 | bool ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data); 76 | void ckh_string_hash(const void *key, size_t r_hash[2]); 77 | bool ckh_string_keycomp(const void *k1, const void *k2); 78 | void ckh_pointer_hash(const void *key, size_t r_hash[2]); 79 | bool ckh_pointer_keycomp(const void *k1, const void *k2); 80 | 81 | #endif /* JEMALLOC_H_EXTERNS */ 82 | /******************************************************************************/ 83 | #ifdef JEMALLOC_H_INLINES 84 | 85 | #endif /* JEMALLOC_H_INLINES */ 86 | /******************************************************************************/ 87 | -------------------------------------------------------------------------------- /test/integration/thread_tcache_enabled.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | static const bool config_tcache = 4 | #ifdef JEMALLOC_TCACHE 5 | true 6 | #else 7 | false 8 | #endif 9 | ; 10 | 11 | void * 12 | thd_start(void *arg) 13 | { 14 | int err; 15 | size_t sz; 16 | bool e0, e1; 17 | 18 | sz = sizeof(bool); 19 | if ((err = mallctl("thread.tcache.enabled", &e0, &sz, NULL, 0))) { 20 | if (err == ENOENT) { 21 | assert_false(config_tcache, 22 | "ENOENT should only be returned if tcache is " 23 | "disabled"); 24 | } 25 | goto label_ENOENT; 26 | } 27 | 28 | if (e0) { 29 | e1 = false; 30 | assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 31 | 0, "Unexpected mallctl() error"); 32 | assert_true(e0, "tcache should be enabled"); 33 | } 34 | 35 | e1 = true; 36 | assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0, 37 | "Unexpected mallctl() error"); 38 | assert_false(e0, "tcache should be disabled"); 39 | 40 | e1 = true; 41 | assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0, 42 | "Unexpected mallctl() error"); 43 | assert_true(e0, "tcache should be enabled"); 44 | 45 | e1 = false; 46 | assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0, 47 | "Unexpected mallctl() error"); 48 | assert_true(e0, "tcache should be enabled"); 49 | 50 | e1 = false; 51 | assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0, 52 | "Unexpected mallctl() error"); 53 | assert_false(e0, "tcache should be disabled"); 54 | 55 | free(malloc(1)); 56 | e1 = true; 57 | assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0, 58 | "Unexpected mallctl() error"); 59 | assert_false(e0, "tcache should be disabled"); 60 | 61 | free(malloc(1)); 62 | e1 = true; 63 | assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0, 64 | "Unexpected mallctl() error"); 65 | assert_true(e0, "tcache should be enabled"); 66 | 67 | free(malloc(1)); 68 | e1 = false; 69 | assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0, 70 | "Unexpected mallctl() error"); 71 | assert_true(e0, "tcache should be enabled"); 72 | 73 | free(malloc(1)); 74 | e1 = false; 75 | assert_d_eq(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz), 0, 76 | "Unexpected mallctl() error"); 77 | assert_false(e0, "tcache should be disabled"); 78 | 79 | free(malloc(1)); 80 | return (NULL); 81 | label_ENOENT: 82 | test_skip("\"thread.tcache.enabled\" mallctl not available"); 83 | return (NULL); 84 | } 85 | 86 | TEST_BEGIN(test_main_thread) 87 | { 88 | 89 | thd_start(NULL); 90 | } 91 | TEST_END 92 | 93 | TEST_BEGIN(test_subthread) 94 | { 95 | thd_t thd; 96 | 97 | thd_create(&thd, thd_start, NULL); 98 | thd_join(thd, NULL); 99 | } 100 | TEST_END 101 | 102 | int 103 | main(void) 104 | { 105 | 106 | /* Run tests multiple times to check for bad interactions. */ 107 | return (test( 108 | test_main_thread, 109 | test_subthread, 110 | test_main_thread, 111 | test_subthread, 112 | test_main_thread)); 113 | } 114 | -------------------------------------------------------------------------------- /test/unit/quarantine.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define QUARANTINE_SIZE 8192 4 | #define STRINGIFY_HELPER(x) #x 5 | #define STRINGIFY(x) STRINGIFY_HELPER(x) 6 | 7 | #ifdef JEMALLOC_FILL 8 | const char *malloc_conf = "abort:false,junk:true,redzone:true,quarantine:" 9 | STRINGIFY(QUARANTINE_SIZE); 10 | #endif 11 | 12 | void 13 | quarantine_clear(void) 14 | { 15 | void *p; 16 | 17 | p = mallocx(QUARANTINE_SIZE*2, 0); 18 | assert_ptr_not_null(p, "Unexpected mallocx() failure"); 19 | dallocx(p, 0); 20 | } 21 | 22 | TEST_BEGIN(test_quarantine) 23 | { 24 | #define SZ ZU(256) 25 | #define NQUARANTINED (QUARANTINE_SIZE/SZ) 26 | void *quarantined[NQUARANTINED+1]; 27 | size_t i, j; 28 | 29 | test_skip_if(!config_fill); 30 | 31 | assert_zu_eq(nallocx(SZ, 0), SZ, 32 | "SZ=%zu does not precisely equal a size class", SZ); 33 | 34 | quarantine_clear(); 35 | 36 | /* 37 | * Allocate enough regions to completely fill the quarantine, plus one 38 | * more. The last iteration occurs with a completely full quarantine, 39 | * but no regions should be drained from the quarantine until the last 40 | * deallocation occurs. Therefore no region recycling should occur 41 | * until after this loop completes. 42 | */ 43 | for (i = 0; i < NQUARANTINED+1; i++) { 44 | void *p = mallocx(SZ, 0); 45 | assert_ptr_not_null(p, "Unexpected mallocx() failure"); 46 | quarantined[i] = p; 47 | dallocx(p, 0); 48 | for (j = 0; j < i; j++) { 49 | assert_ptr_ne(p, quarantined[j], 50 | "Quarantined region recycled too early; " 51 | "i=%zu, j=%zu", i, j); 52 | } 53 | } 54 | #undef NQUARANTINED 55 | #undef SZ 56 | } 57 | TEST_END 58 | 59 | static bool detected_redzone_corruption; 60 | 61 | static void 62 | arena_redzone_corruption_replacement(void *ptr, size_t usize, bool after, 63 | size_t offset, uint8_t byte) 64 | { 65 | 66 | detected_redzone_corruption = true; 67 | } 68 | 69 | TEST_BEGIN(test_quarantine_redzone) 70 | { 71 | char *s; 72 | arena_redzone_corruption_t *arena_redzone_corruption_orig; 73 | 74 | test_skip_if(!config_fill); 75 | 76 | arena_redzone_corruption_orig = arena_redzone_corruption; 77 | arena_redzone_corruption = arena_redzone_corruption_replacement; 78 | 79 | /* Test underflow. */ 80 | detected_redzone_corruption = false; 81 | s = (char *)mallocx(1, 0); 82 | assert_ptr_not_null((void *)s, "Unexpected mallocx() failure"); 83 | s[-1] = 0xbb; 84 | dallocx(s, 0); 85 | assert_true(detected_redzone_corruption, 86 | "Did not detect redzone corruption"); 87 | 88 | /* Test overflow. */ 89 | detected_redzone_corruption = false; 90 | s = (char *)mallocx(1, 0); 91 | assert_ptr_not_null((void *)s, "Unexpected mallocx() failure"); 92 | s[sallocx(s, 0)] = 0xbb; 93 | dallocx(s, 0); 94 | assert_true(detected_redzone_corruption, 95 | "Did not detect redzone corruption"); 96 | 97 | arena_redzone_corruption = arena_redzone_corruption_orig; 98 | } 99 | TEST_END 100 | 101 | int 102 | main(void) 103 | { 104 | 105 | return (test( 106 | test_quarantine, 107 | test_quarantine_redzone)); 108 | } 109 | -------------------------------------------------------------------------------- /test/unit/smoothstep.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | static const uint64_t smoothstep_tab[] = { 4 | #define STEP(step, h, x, y) \ 5 | h, 6 | SMOOTHSTEP 7 | #undef STEP 8 | }; 9 | 10 | TEST_BEGIN(test_smoothstep_integral) 11 | { 12 | uint64_t sum, min, max; 13 | unsigned i; 14 | 15 | /* 16 | * The integral of smoothstep in the [0..1] range equals 1/2. Verify 17 | * that the fixed point representation's integral is no more than 18 | * rounding error distant from 1/2. Regarding rounding, each table 19 | * element is rounded down to the nearest fixed point value, so the 20 | * integral may be off by as much as SMOOTHSTEP_NSTEPS ulps. 21 | */ 22 | sum = 0; 23 | for (i = 0; i < SMOOTHSTEP_NSTEPS; i++) 24 | sum += smoothstep_tab[i]; 25 | 26 | max = (KQU(1) << (SMOOTHSTEP_BFP-1)) * (SMOOTHSTEP_NSTEPS+1); 27 | min = max - SMOOTHSTEP_NSTEPS; 28 | 29 | assert_u64_ge(sum, min, 30 | "Integral too small, even accounting for truncation"); 31 | assert_u64_le(sum, max, "Integral exceeds 1/2"); 32 | if (false) { 33 | malloc_printf("%"FMTu64" ulps under 1/2 (limit %d)\n", 34 | max - sum, SMOOTHSTEP_NSTEPS); 35 | } 36 | } 37 | TEST_END 38 | 39 | TEST_BEGIN(test_smoothstep_monotonic) 40 | { 41 | uint64_t prev_h; 42 | unsigned i; 43 | 44 | /* 45 | * The smoothstep function is monotonic in [0..1], i.e. its slope is 46 | * non-negative. In practice we want to parametrize table generation 47 | * such that piecewise slope is greater than zero, but do not require 48 | * that here. 49 | */ 50 | prev_h = 0; 51 | for (i = 0; i < SMOOTHSTEP_NSTEPS; i++) { 52 | uint64_t h = smoothstep_tab[i]; 53 | assert_u64_ge(h, prev_h, "Piecewise non-monotonic, i=%u", i); 54 | prev_h = h; 55 | } 56 | assert_u64_eq(smoothstep_tab[SMOOTHSTEP_NSTEPS-1], 57 | (KQU(1) << SMOOTHSTEP_BFP), "Last step must equal 1"); 58 | } 59 | TEST_END 60 | 61 | TEST_BEGIN(test_smoothstep_slope) 62 | { 63 | uint64_t prev_h, prev_delta; 64 | unsigned i; 65 | 66 | /* 67 | * The smoothstep slope strictly increases until x=0.5, and then 68 | * strictly decreases until x=1.0. Verify the slightly weaker 69 | * requirement of monotonicity, so that inadequate table precision does 70 | * not cause false test failures. 71 | */ 72 | prev_h = 0; 73 | prev_delta = 0; 74 | for (i = 0; i < SMOOTHSTEP_NSTEPS / 2 + SMOOTHSTEP_NSTEPS % 2; i++) { 75 | uint64_t h = smoothstep_tab[i]; 76 | uint64_t delta = h - prev_h; 77 | assert_u64_ge(delta, prev_delta, 78 | "Slope must monotonically increase in 0.0 <= x <= 0.5, " 79 | "i=%u", i); 80 | prev_h = h; 81 | prev_delta = delta; 82 | } 83 | 84 | prev_h = KQU(1) << SMOOTHSTEP_BFP; 85 | prev_delta = 0; 86 | for (i = SMOOTHSTEP_NSTEPS-1; i >= SMOOTHSTEP_NSTEPS / 2; i--) { 87 | uint64_t h = smoothstep_tab[i]; 88 | uint64_t delta = prev_h - h; 89 | assert_u64_ge(delta, prev_delta, 90 | "Slope must monotonically decrease in 0.5 <= x <= 1.0, " 91 | "i=%u", i); 92 | prev_h = h; 93 | prev_delta = delta; 94 | } 95 | } 96 | TEST_END 97 | 98 | int 99 | main(void) 100 | { 101 | 102 | return (test( 103 | test_smoothstep_integral, 104 | test_smoothstep_monotonic, 105 | test_smoothstep_slope)); 106 | } 107 | -------------------------------------------------------------------------------- /test/src/test.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | static unsigned test_count = 0; 4 | static test_status_t test_counts[test_status_count] = {0, 0, 0}; 5 | static test_status_t test_status = test_status_pass; 6 | static const char * test_name = ""; 7 | 8 | JEMALLOC_FORMAT_PRINTF(1, 2) 9 | void 10 | test_skip(const char *format, ...) 11 | { 12 | va_list ap; 13 | 14 | va_start(ap, format); 15 | malloc_vcprintf(NULL, NULL, format, ap); 16 | va_end(ap); 17 | malloc_printf("\n"); 18 | test_status = test_status_skip; 19 | } 20 | 21 | JEMALLOC_FORMAT_PRINTF(1, 2) 22 | void 23 | test_fail(const char *format, ...) 24 | { 25 | va_list ap; 26 | 27 | va_start(ap, format); 28 | malloc_vcprintf(NULL, NULL, format, ap); 29 | va_end(ap); 30 | malloc_printf("\n"); 31 | test_status = test_status_fail; 32 | } 33 | 34 | static const char * 35 | test_status_string(test_status_t test_status) 36 | { 37 | 38 | switch (test_status) { 39 | case test_status_pass: return "pass"; 40 | case test_status_skip: return "skip"; 41 | case test_status_fail: return "fail"; 42 | default: not_reached(); 43 | } 44 | } 45 | 46 | void 47 | p_test_init(const char *name) 48 | { 49 | 50 | test_count++; 51 | test_status = test_status_pass; 52 | test_name = name; 53 | } 54 | 55 | void 56 | p_test_fini(void) 57 | { 58 | 59 | test_counts[test_status]++; 60 | malloc_printf("%s: %s\n", test_name, test_status_string(test_status)); 61 | } 62 | 63 | static test_status_t 64 | p_test_impl(bool do_malloc_init, test_t *t, va_list ap) 65 | { 66 | test_status_t ret; 67 | 68 | if (do_malloc_init) { 69 | /* 70 | * Make sure initialization occurs prior to running tests. 71 | * Tests are special because they may use internal facilities 72 | * prior to triggering initialization as a side effect of 73 | * calling into the public API. 74 | */ 75 | if (nallocx(1, 0) == 0) { 76 | malloc_printf("Initialization error"); 77 | return (test_status_fail); 78 | } 79 | } 80 | 81 | ret = test_status_pass; 82 | for (; t != NULL; t = va_arg(ap, test_t *)) { 83 | t(); 84 | if (test_status > ret) 85 | ret = test_status; 86 | } 87 | 88 | malloc_printf("--- %s: %u/%u, %s: %u/%u, %s: %u/%u ---\n", 89 | test_status_string(test_status_pass), 90 | test_counts[test_status_pass], test_count, 91 | test_status_string(test_status_skip), 92 | test_counts[test_status_skip], test_count, 93 | test_status_string(test_status_fail), 94 | test_counts[test_status_fail], test_count); 95 | 96 | return (ret); 97 | } 98 | 99 | test_status_t 100 | p_test(test_t *t, ...) 101 | { 102 | test_status_t ret; 103 | va_list ap; 104 | 105 | ret = test_status_pass; 106 | va_start(ap, t); 107 | ret = p_test_impl(true, t, ap); 108 | va_end(ap); 109 | 110 | return (ret); 111 | } 112 | 113 | test_status_t 114 | p_test_no_malloc_init(test_t *t, ...) 115 | { 116 | test_status_t ret; 117 | va_list ap; 118 | 119 | ret = test_status_pass; 120 | va_start(ap, t); 121 | ret = p_test_impl(false, t, ap); 122 | va_end(ap); 123 | 124 | return (ret); 125 | } 126 | 127 | void 128 | p_test_fail(const char *prefix, const char *message) 129 | { 130 | 131 | malloc_cprintf(NULL, NULL, "%s%s\n", prefix, message); 132 | test_status = test_status_fail; 133 | } 134 | -------------------------------------------------------------------------------- /include/jemalloc/internal/mb.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | #endif /* JEMALLOC_H_TYPES */ 5 | /******************************************************************************/ 6 | #ifdef JEMALLOC_H_STRUCTS 7 | 8 | #endif /* JEMALLOC_H_STRUCTS */ 9 | /******************************************************************************/ 10 | #ifdef JEMALLOC_H_EXTERNS 11 | 12 | #endif /* JEMALLOC_H_EXTERNS */ 13 | /******************************************************************************/ 14 | #ifdef JEMALLOC_H_INLINES 15 | 16 | #ifndef JEMALLOC_ENABLE_INLINE 17 | void mb_write(void); 18 | #endif 19 | 20 | #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MB_C_)) 21 | #ifdef __i386__ 22 | /* 23 | * According to the Intel Architecture Software Developer's Manual, current 24 | * processors execute instructions in order from the perspective of other 25 | * processors in a multiprocessor system, but 1) Intel reserves the right to 26 | * change that, and 2) the compiler's optimizer could re-order instructions if 27 | * there weren't some form of barrier. Therefore, even if running on an 28 | * architecture that does not need memory barriers (everything through at least 29 | * i686), an "optimizer barrier" is necessary. 30 | */ 31 | JEMALLOC_INLINE void 32 | mb_write(void) 33 | { 34 | 35 | # if 0 36 | /* This is a true memory barrier. */ 37 | asm volatile ("pusha;" 38 | "xor %%eax,%%eax;" 39 | "cpuid;" 40 | "popa;" 41 | : /* Outputs. */ 42 | : /* Inputs. */ 43 | : "memory" /* Clobbers. */ 44 | ); 45 | # else 46 | /* 47 | * This is hopefully enough to keep the compiler from reordering 48 | * instructions around this one. 49 | */ 50 | asm volatile ("nop;" 51 | : /* Outputs. */ 52 | : /* Inputs. */ 53 | : "memory" /* Clobbers. */ 54 | ); 55 | # endif 56 | } 57 | #elif (defined(__amd64__) || defined(__x86_64__)) 58 | JEMALLOC_INLINE void 59 | mb_write(void) 60 | { 61 | 62 | asm volatile ("sfence" 63 | : /* Outputs. */ 64 | : /* Inputs. */ 65 | : "memory" /* Clobbers. */ 66 | ); 67 | } 68 | #elif defined(__powerpc__) 69 | JEMALLOC_INLINE void 70 | mb_write(void) 71 | { 72 | 73 | asm volatile ("eieio" 74 | : /* Outputs. */ 75 | : /* Inputs. */ 76 | : "memory" /* Clobbers. */ 77 | ); 78 | } 79 | #elif defined(__sparc64__) 80 | JEMALLOC_INLINE void 81 | mb_write(void) 82 | { 83 | 84 | asm volatile ("membar #StoreStore" 85 | : /* Outputs. */ 86 | : /* Inputs. */ 87 | : "memory" /* Clobbers. */ 88 | ); 89 | } 90 | #elif defined(__tile__) 91 | JEMALLOC_INLINE void 92 | mb_write(void) 93 | { 94 | 95 | __sync_synchronize(); 96 | } 97 | #else 98 | /* 99 | * This is much slower than a simple memory barrier, but the semantics of mutex 100 | * unlock make this work. 101 | */ 102 | JEMALLOC_INLINE void 103 | mb_write(void) 104 | { 105 | malloc_mutex_t mtx; 106 | 107 | malloc_mutex_init(&mtx, "mb", WITNESS_RANK_OMIT); 108 | malloc_mutex_lock(TSDN_NULL, &mtx); 109 | malloc_mutex_unlock(TSDN_NULL, &mtx); 110 | } 111 | #endif 112 | #endif 113 | 114 | #endif /* JEMALLOC_H_INLINES */ 115 | /******************************************************************************/ 116 | -------------------------------------------------------------------------------- /src/bitmap.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_BITMAP_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | /******************************************************************************/ 5 | 6 | #ifdef USE_TREE 7 | 8 | void 9 | bitmap_info_init(bitmap_info_t *binfo, size_t nbits) 10 | { 11 | unsigned i; 12 | size_t group_count; 13 | 14 | assert(nbits > 0); 15 | assert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS)); 16 | 17 | /* 18 | * Compute the number of groups necessary to store nbits bits, and 19 | * progressively work upward through the levels until reaching a level 20 | * that requires only one group. 21 | */ 22 | binfo->levels[0].group_offset = 0; 23 | group_count = BITMAP_BITS2GROUPS(nbits); 24 | for (i = 1; group_count > 1; i++) { 25 | assert(i < BITMAP_MAX_LEVELS); 26 | binfo->levels[i].group_offset = binfo->levels[i-1].group_offset 27 | + group_count; 28 | group_count = BITMAP_BITS2GROUPS(group_count); 29 | } 30 | binfo->levels[i].group_offset = binfo->levels[i-1].group_offset 31 | + group_count; 32 | assert(binfo->levels[i].group_offset <= BITMAP_GROUPS_MAX); 33 | binfo->nlevels = i; 34 | binfo->nbits = nbits; 35 | } 36 | 37 | static size_t 38 | bitmap_info_ngroups(const bitmap_info_t *binfo) 39 | { 40 | 41 | return (binfo->levels[binfo->nlevels].group_offset); 42 | } 43 | 44 | void 45 | bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo) 46 | { 47 | size_t extra; 48 | unsigned i; 49 | 50 | /* 51 | * Bits are actually inverted with regard to the external bitmap 52 | * interface, so the bitmap starts out with all 1 bits, except for 53 | * trailing unused bits (if any). Note that each group uses bit 0 to 54 | * correspond to the first logical bit in the group, so extra bits 55 | * are the most significant bits of the last group. 56 | */ 57 | memset(bitmap, 0xffU, bitmap_size(binfo)); 58 | extra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK)) 59 | & BITMAP_GROUP_NBITS_MASK; 60 | if (extra != 0) 61 | bitmap[binfo->levels[1].group_offset - 1] >>= extra; 62 | for (i = 1; i < binfo->nlevels; i++) { 63 | size_t group_count = binfo->levels[i].group_offset - 64 | binfo->levels[i-1].group_offset; 65 | extra = (BITMAP_GROUP_NBITS - (group_count & 66 | BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK; 67 | if (extra != 0) 68 | bitmap[binfo->levels[i+1].group_offset - 1] >>= extra; 69 | } 70 | } 71 | 72 | #else /* USE_TREE */ 73 | 74 | void 75 | bitmap_info_init(bitmap_info_t *binfo, size_t nbits) 76 | { 77 | 78 | assert(nbits > 0); 79 | assert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS)); 80 | 81 | binfo->ngroups = BITMAP_BITS2GROUPS(nbits); 82 | binfo->nbits = nbits; 83 | } 84 | 85 | static size_t 86 | bitmap_info_ngroups(const bitmap_info_t *binfo) 87 | { 88 | 89 | return (binfo->ngroups); 90 | } 91 | 92 | void 93 | bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo) 94 | { 95 | size_t extra; 96 | 97 | memset(bitmap, 0xffU, bitmap_size(binfo)); 98 | extra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK)) 99 | & BITMAP_GROUP_NBITS_MASK; 100 | if (extra != 0) 101 | bitmap[binfo->ngroups - 1] >>= extra; 102 | } 103 | 104 | #endif /* USE_TREE */ 105 | 106 | size_t 107 | bitmap_size(const bitmap_info_t *binfo) 108 | { 109 | 110 | return (bitmap_info_ngroups(binfo) << LG_SIZEOF_BITMAP); 111 | } 112 | -------------------------------------------------------------------------------- /test/include/test/mq.h: -------------------------------------------------------------------------------- 1 | void mq_nanosleep(unsigned ns); 2 | 3 | /* 4 | * Simple templated message queue implementation that relies on only mutexes for 5 | * synchronization (which reduces portability issues). Given the following 6 | * setup: 7 | * 8 | * typedef struct mq_msg_s mq_msg_t; 9 | * struct mq_msg_s { 10 | * mq_msg(mq_msg_t) link; 11 | * [message data] 12 | * }; 13 | * mq_gen(, mq_, mq_t, mq_msg_t, link) 14 | * 15 | * The API is as follows: 16 | * 17 | * bool mq_init(mq_t *mq); 18 | * void mq_fini(mq_t *mq); 19 | * unsigned mq_count(mq_t *mq); 20 | * mq_msg_t *mq_tryget(mq_t *mq); 21 | * mq_msg_t *mq_get(mq_t *mq); 22 | * void mq_put(mq_t *mq, mq_msg_t *msg); 23 | * 24 | * The message queue linkage embedded in each message is to be treated as 25 | * externally opaque (no need to initialize or clean up externally). mq_fini() 26 | * does not perform any cleanup of messages, since it knows nothing of their 27 | * payloads. 28 | */ 29 | #define mq_msg(a_mq_msg_type) ql_elm(a_mq_msg_type) 30 | 31 | #define mq_gen(a_attr, a_prefix, a_mq_type, a_mq_msg_type, a_field) \ 32 | typedef struct { \ 33 | mtx_t lock; \ 34 | ql_head(a_mq_msg_type) msgs; \ 35 | unsigned count; \ 36 | } a_mq_type; \ 37 | a_attr bool \ 38 | a_prefix##init(a_mq_type *mq) { \ 39 | \ 40 | if (mtx_init(&mq->lock)) \ 41 | return (true); \ 42 | ql_new(&mq->msgs); \ 43 | mq->count = 0; \ 44 | return (false); \ 45 | } \ 46 | a_attr void \ 47 | a_prefix##fini(a_mq_type *mq) \ 48 | { \ 49 | \ 50 | mtx_fini(&mq->lock); \ 51 | } \ 52 | a_attr unsigned \ 53 | a_prefix##count(a_mq_type *mq) \ 54 | { \ 55 | unsigned count; \ 56 | \ 57 | mtx_lock(&mq->lock); \ 58 | count = mq->count; \ 59 | mtx_unlock(&mq->lock); \ 60 | return (count); \ 61 | } \ 62 | a_attr a_mq_msg_type * \ 63 | a_prefix##tryget(a_mq_type *mq) \ 64 | { \ 65 | a_mq_msg_type *msg; \ 66 | \ 67 | mtx_lock(&mq->lock); \ 68 | msg = ql_first(&mq->msgs); \ 69 | if (msg != NULL) { \ 70 | ql_head_remove(&mq->msgs, a_mq_msg_type, a_field); \ 71 | mq->count--; \ 72 | } \ 73 | mtx_unlock(&mq->lock); \ 74 | return (msg); \ 75 | } \ 76 | a_attr a_mq_msg_type * \ 77 | a_prefix##get(a_mq_type *mq) \ 78 | { \ 79 | a_mq_msg_type *msg; \ 80 | unsigned ns; \ 81 | \ 82 | msg = a_prefix##tryget(mq); \ 83 | if (msg != NULL) \ 84 | return (msg); \ 85 | \ 86 | ns = 1; \ 87 | while (true) { \ 88 | mq_nanosleep(ns); \ 89 | msg = a_prefix##tryget(mq); \ 90 | if (msg != NULL) \ 91 | return (msg); \ 92 | if (ns < 1000*1000*1000) { \ 93 | /* Double sleep time, up to max 1 second. */ \ 94 | ns <<= 1; \ 95 | if (ns > 1000*1000*1000) \ 96 | ns = 1000*1000*1000; \ 97 | } \ 98 | } \ 99 | } \ 100 | a_attr void \ 101 | a_prefix##put(a_mq_type *mq, a_mq_msg_type *msg) \ 102 | { \ 103 | \ 104 | mtx_lock(&mq->lock); \ 105 | ql_elm_new(msg, a_field); \ 106 | ql_tail_insert(&mq->msgs, msg, a_field); \ 107 | mq->count++; \ 108 | mtx_unlock(&mq->lock); \ 109 | } 110 | -------------------------------------------------------------------------------- /include/jemalloc/jemalloc_protos.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * The @je_@ prefix on the following public symbol declarations is an artifact 3 | * of namespace management, and should be omitted in application code unless 4 | * JEMALLOC_NO_DEMANGLE is defined (see jemalloc_mangle@install_suffix@.h). 5 | */ 6 | extern JEMALLOC_EXPORT const char *@je_@malloc_conf; 7 | extern JEMALLOC_EXPORT void (*@je_@malloc_message)(void *cbopaque, 8 | const char *s); 9 | 10 | JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 11 | void JEMALLOC_NOTHROW *@je_@malloc(size_t size) 12 | JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1); 13 | JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 14 | void JEMALLOC_NOTHROW *@je_@calloc(size_t num, size_t size) 15 | JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2); 16 | JEMALLOC_EXPORT int JEMALLOC_NOTHROW @je_@posix_memalign(void **memptr, 17 | size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1)); 18 | JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 19 | void JEMALLOC_NOTHROW *@je_@aligned_alloc(size_t alignment, 20 | size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) 21 | JEMALLOC_ALLOC_SIZE(2); 22 | JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 23 | void JEMALLOC_NOTHROW *@je_@realloc(void *ptr, size_t size) 24 | JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2); 25 | JEMALLOC_EXPORT void JEMALLOC_NOTHROW @je_@free(void *ptr) 26 | JEMALLOC_CXX_THROW; 27 | 28 | JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 29 | void JEMALLOC_NOTHROW *@je_@mallocx(size_t size, int flags) 30 | JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1); 31 | JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 32 | void JEMALLOC_NOTHROW *@je_@rallocx(void *ptr, size_t size, 33 | int flags) JEMALLOC_ALLOC_SIZE(2); 34 | JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW @je_@xallocx(void *ptr, size_t size, 35 | size_t extra, int flags); 36 | JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW @je_@sallocx(const void *ptr, 37 | int flags) JEMALLOC_ATTR(pure); 38 | JEMALLOC_EXPORT void JEMALLOC_NOTHROW @je_@dallocx(void *ptr, int flags); 39 | JEMALLOC_EXPORT void JEMALLOC_NOTHROW @je_@sdallocx(void *ptr, size_t size, 40 | int flags); 41 | JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW @je_@nallocx(size_t size, int flags) 42 | JEMALLOC_ATTR(pure); 43 | 44 | JEMALLOC_EXPORT int JEMALLOC_NOTHROW @je_@mallctl(const char *name, 45 | void *oldp, size_t *oldlenp, void *newp, size_t newlen); 46 | JEMALLOC_EXPORT int JEMALLOC_NOTHROW @je_@mallctlnametomib(const char *name, 47 | size_t *mibp, size_t *miblenp); 48 | JEMALLOC_EXPORT int JEMALLOC_NOTHROW @je_@mallctlbymib(const size_t *mib, 49 | size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen); 50 | JEMALLOC_EXPORT void JEMALLOC_NOTHROW @je_@malloc_stats_print( 51 | void (*write_cb)(void *, const char *), void *@je_@cbopaque, 52 | const char *opts); 53 | JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW @je_@malloc_usable_size( 54 | JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW; 55 | 56 | #ifdef JEMALLOC_OVERRIDE_MEMALIGN 57 | JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 58 | void JEMALLOC_NOTHROW *@je_@memalign(size_t alignment, size_t size) 59 | JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc); 60 | #endif 61 | 62 | #ifdef JEMALLOC_OVERRIDE_VALLOC 63 | JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 64 | void JEMALLOC_NOTHROW *@je_@valloc(size_t size) JEMALLOC_CXX_THROW 65 | JEMALLOC_ATTR(malloc); 66 | #endif 67 | -------------------------------------------------------------------------------- /msvc/projects/vc2015/test_threads/test_threads.cpp: -------------------------------------------------------------------------------- 1 | // jemalloc C++ threaded test 2 | // Author: Rustam Abdullaev 3 | // Public Domain 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using std::vector; 15 | using std::thread; 16 | using std::uniform_int_distribution; 17 | using std::minstd_rand; 18 | 19 | int test_threads() 20 | { 21 | je_malloc_conf = "narenas:3"; 22 | int narenas = 0; 23 | size_t sz = sizeof(narenas); 24 | je_mallctl("opt.narenas", &narenas, &sz, NULL, 0); 25 | if (narenas != 3) { 26 | printf("Error: unexpected number of arenas: %d\n", narenas); 27 | return 1; 28 | } 29 | static const int sizes[] = { 7, 16, 32, 60, 91, 100, 120, 144, 169, 199, 255, 400, 670, 900, 917, 1025, 3333, 5190, 13131, 49192, 99999, 123123, 255265, 2333111 }; 30 | static const int numSizes = (int)(sizeof(sizes) / sizeof(sizes[0])); 31 | vector workers; 32 | static const int numThreads = narenas + 1, numAllocsMax = 25, numIter1 = 50, numIter2 = 50; 33 | je_malloc_stats_print(NULL, NULL, NULL); 34 | size_t allocated1; 35 | size_t sz1 = sizeof(allocated1); 36 | je_mallctl("stats.active", &allocated1, &sz1, NULL, 0); 37 | printf("\nPress Enter to start threads...\n"); 38 | getchar(); 39 | printf("Starting %d threads x %d x %d iterations...\n", numThreads, numIter1, numIter2); 40 | for (int i = 0; i < numThreads; i++) { 41 | workers.emplace_back([tid=i]() { 42 | uniform_int_distribution sizeDist(0, numSizes - 1); 43 | minstd_rand rnd(tid * 17); 44 | uint8_t* ptrs[numAllocsMax]; 45 | int ptrsz[numAllocsMax]; 46 | for (int i = 0; i < numIter1; ++i) { 47 | thread t([&]() { 48 | for (int i = 0; i < numIter2; ++i) { 49 | const int numAllocs = numAllocsMax - sizeDist(rnd); 50 | for (int j = 0; j < numAllocs; j += 64) { 51 | const int x = sizeDist(rnd); 52 | const int sz = sizes[x]; 53 | ptrsz[j] = sz; 54 | ptrs[j] = (uint8_t*)je_malloc(sz); 55 | if (!ptrs[j]) { 56 | printf("Unable to allocate %d bytes in thread %d, iter %d, alloc %d. %d\n", sz, tid, i, j, x); 57 | exit(1); 58 | } 59 | for (int k = 0; k < sz; k++) 60 | ptrs[j][k] = tid + k; 61 | } 62 | for (int j = 0; j < numAllocs; j += 64) { 63 | for (int k = 0, sz = ptrsz[j]; k < sz; k++) 64 | if (ptrs[j][k] != (uint8_t)(tid + k)) { 65 | printf("Memory error in thread %d, iter %d, alloc %d @ %d : %02X!=%02X\n", tid, i, j, k, ptrs[j][k], (uint8_t)(tid + k)); 66 | exit(1); 67 | } 68 | je_free(ptrs[j]); 69 | } 70 | } 71 | }); 72 | t.join(); 73 | } 74 | }); 75 | } 76 | for (thread& t : workers) { 77 | t.join(); 78 | } 79 | je_malloc_stats_print(NULL, NULL, NULL); 80 | size_t allocated2; 81 | je_mallctl("stats.active", &allocated2, &sz1, NULL, 0); 82 | size_t leaked = allocated2 - allocated1; 83 | printf("\nDone. Leaked: %zd bytes\n", leaked); 84 | bool failed = leaked > 65536; // in case C++ runtime allocated something (e.g. iostream locale or facet) 85 | printf("\nTest %s!\n", (failed ? "FAILED" : "successful")); 86 | printf("\nPress Enter to continue...\n"); 87 | getchar(); 88 | return failed ? 1 : 0; 89 | } 90 | -------------------------------------------------------------------------------- /include/jemalloc/internal/chunk.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | /* 5 | * Size and alignment of memory chunks that are allocated by the OS's virtual 6 | * memory system. 7 | */ 8 | #define LG_CHUNK_DEFAULT 21 9 | 10 | /* Return the chunk address for allocation address a. */ 11 | #define CHUNK_ADDR2BASE(a) \ 12 | ((void *)((uintptr_t)(a) & ~chunksize_mask)) 13 | 14 | /* Return the chunk offset of address a. */ 15 | #define CHUNK_ADDR2OFFSET(a) \ 16 | ((size_t)((uintptr_t)(a) & chunksize_mask)) 17 | 18 | /* Return the smallest chunk multiple that is >= s. */ 19 | #define CHUNK_CEILING(s) \ 20 | (((s) + chunksize_mask) & ~chunksize_mask) 21 | 22 | #define CHUNK_HOOKS_INITIALIZER { \ 23 | NULL, \ 24 | NULL, \ 25 | NULL, \ 26 | NULL, \ 27 | NULL, \ 28 | NULL, \ 29 | NULL \ 30 | } 31 | 32 | #endif /* JEMALLOC_H_TYPES */ 33 | /******************************************************************************/ 34 | #ifdef JEMALLOC_H_STRUCTS 35 | 36 | #endif /* JEMALLOC_H_STRUCTS */ 37 | /******************************************************************************/ 38 | #ifdef JEMALLOC_H_EXTERNS 39 | 40 | extern size_t opt_lg_chunk; 41 | extern const char *opt_dss; 42 | 43 | extern rtree_t chunks_rtree; 44 | 45 | extern size_t chunksize; 46 | extern size_t chunksize_mask; /* (chunksize - 1). */ 47 | extern size_t chunk_npages; 48 | 49 | extern const chunk_hooks_t chunk_hooks_default; 50 | 51 | chunk_hooks_t chunk_hooks_get(tsdn_t *tsdn, arena_t *arena); 52 | chunk_hooks_t chunk_hooks_set(tsdn_t *tsdn, arena_t *arena, 53 | const chunk_hooks_t *chunk_hooks); 54 | 55 | bool chunk_register(tsdn_t *tsdn, const void *chunk, 56 | const extent_node_t *node); 57 | void chunk_deregister(const void *chunk, const extent_node_t *node); 58 | void *chunk_alloc_base(size_t size); 59 | void *chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena, 60 | chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment, 61 | bool *zero, bool *commit, bool dalloc_node); 62 | void *chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena, 63 | chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment, 64 | bool *zero, bool *commit); 65 | void chunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena, 66 | chunk_hooks_t *chunk_hooks, void *chunk, size_t size, bool committed); 67 | void chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, 68 | chunk_hooks_t *chunk_hooks, void *chunk, size_t size, bool zeroed, 69 | bool committed); 70 | bool chunk_purge_wrapper(tsdn_t *tsdn, arena_t *arena, 71 | chunk_hooks_t *chunk_hooks, void *chunk, size_t size, size_t offset, 72 | size_t length); 73 | bool chunk_boot(void); 74 | 75 | #endif /* JEMALLOC_H_EXTERNS */ 76 | /******************************************************************************/ 77 | #ifdef JEMALLOC_H_INLINES 78 | 79 | #ifndef JEMALLOC_ENABLE_INLINE 80 | extent_node_t *chunk_lookup(const void *chunk, bool dependent); 81 | #endif 82 | 83 | #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_CHUNK_C_)) 84 | JEMALLOC_INLINE extent_node_t * 85 | chunk_lookup(const void *ptr, bool dependent) 86 | { 87 | 88 | return (rtree_get(&chunks_rtree, (uintptr_t)ptr, dependent)); 89 | } 90 | #endif 91 | 92 | #endif /* JEMALLOC_H_INLINES */ 93 | /******************************************************************************/ 94 | 95 | #include "jemalloc/internal/chunk_dss.h" 96 | #include "jemalloc/internal/chunk_mmap.h" 97 | -------------------------------------------------------------------------------- /test/integration/posix_memalign.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define CHUNK 0x400000 4 | #define MAXALIGN (((size_t)1) << 23) 5 | 6 | /* 7 | * On systems which can't merge extents, tests that call this function generate 8 | * a lot of dirty memory very quickly. Purging between cycles mitigates 9 | * potential OOM on e.g. 32-bit Windows. 10 | */ 11 | static void 12 | purge(void) 13 | { 14 | 15 | assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, 16 | "Unexpected mallctl error"); 17 | } 18 | 19 | TEST_BEGIN(test_alignment_errors) 20 | { 21 | size_t alignment; 22 | void *p; 23 | 24 | for (alignment = 0; alignment < sizeof(void *); alignment++) { 25 | assert_d_eq(posix_memalign(&p, alignment, 1), EINVAL, 26 | "Expected error for invalid alignment %zu", 27 | alignment); 28 | } 29 | 30 | for (alignment = sizeof(size_t); alignment < MAXALIGN; 31 | alignment <<= 1) { 32 | assert_d_ne(posix_memalign(&p, alignment + 1, 1), 0, 33 | "Expected error for invalid alignment %zu", 34 | alignment + 1); 35 | } 36 | } 37 | TEST_END 38 | 39 | TEST_BEGIN(test_oom_errors) 40 | { 41 | size_t alignment, size; 42 | void *p; 43 | 44 | #if LG_SIZEOF_PTR == 3 45 | alignment = UINT64_C(0x8000000000000000); 46 | size = UINT64_C(0x8000000000000000); 47 | #else 48 | alignment = 0x80000000LU; 49 | size = 0x80000000LU; 50 | #endif 51 | assert_d_ne(posix_memalign(&p, alignment, size), 0, 52 | "Expected error for posix_memalign(&p, %zu, %zu)", 53 | alignment, size); 54 | 55 | #if LG_SIZEOF_PTR == 3 56 | alignment = UINT64_C(0x4000000000000000); 57 | size = UINT64_C(0xc000000000000001); 58 | #else 59 | alignment = 0x40000000LU; 60 | size = 0xc0000001LU; 61 | #endif 62 | assert_d_ne(posix_memalign(&p, alignment, size), 0, 63 | "Expected error for posix_memalign(&p, %zu, %zu)", 64 | alignment, size); 65 | 66 | alignment = 0x10LU; 67 | #if LG_SIZEOF_PTR == 3 68 | size = UINT64_C(0xfffffffffffffff0); 69 | #else 70 | size = 0xfffffff0LU; 71 | #endif 72 | assert_d_ne(posix_memalign(&p, alignment, size), 0, 73 | "Expected error for posix_memalign(&p, %zu, %zu)", 74 | alignment, size); 75 | } 76 | TEST_END 77 | 78 | TEST_BEGIN(test_alignment_and_size) 79 | { 80 | #define NITER 4 81 | size_t alignment, size, total; 82 | unsigned i; 83 | int err; 84 | void *ps[NITER]; 85 | 86 | for (i = 0; i < NITER; i++) 87 | ps[i] = NULL; 88 | 89 | for (alignment = 8; 90 | alignment <= MAXALIGN; 91 | alignment <<= 1) { 92 | total = 0; 93 | for (size = 1; 94 | size < 3 * alignment && size < (1U << 31); 95 | size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { 96 | for (i = 0; i < NITER; i++) { 97 | err = posix_memalign(&ps[i], 98 | alignment, size); 99 | if (err) { 100 | char buf[BUFERROR_BUF]; 101 | 102 | buferror(get_errno(), buf, sizeof(buf)); 103 | test_fail( 104 | "Error for alignment=%zu, " 105 | "size=%zu (%#zx): %s", 106 | alignment, size, size, buf); 107 | } 108 | total += malloc_usable_size(ps[i]); 109 | if (total >= (MAXALIGN << 1)) 110 | break; 111 | } 112 | for (i = 0; i < NITER; i++) { 113 | if (ps[i] != NULL) { 114 | free(ps[i]); 115 | ps[i] = NULL; 116 | } 117 | } 118 | } 119 | purge(); 120 | } 121 | #undef NITER 122 | } 123 | TEST_END 124 | 125 | int 126 | main(void) 127 | { 128 | 129 | return (test( 130 | test_alignment_errors, 131 | test_oom_errors, 132 | test_alignment_and_size)); 133 | } 134 | -------------------------------------------------------------------------------- /test/unit/atomic.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define TEST_STRUCT(p, t) \ 4 | struct p##_test_s { \ 5 | t accum0; \ 6 | t x; \ 7 | t s; \ 8 | }; \ 9 | typedef struct p##_test_s p##_test_t; 10 | 11 | #define TEST_BODY(p, t, tc, ta, FMT) do { \ 12 | const p##_test_t tests[] = { \ 13 | {(t)-1, (t)-1, (t)-2}, \ 14 | {(t)-1, (t) 0, (t)-2}, \ 15 | {(t)-1, (t) 1, (t)-2}, \ 16 | \ 17 | {(t) 0, (t)-1, (t)-2}, \ 18 | {(t) 0, (t) 0, (t)-2}, \ 19 | {(t) 0, (t) 1, (t)-2}, \ 20 | \ 21 | {(t) 1, (t)-1, (t)-2}, \ 22 | {(t) 1, (t) 0, (t)-2}, \ 23 | {(t) 1, (t) 1, (t)-2}, \ 24 | \ 25 | {(t)0, (t)-(1 << 22), (t)-2}, \ 26 | {(t)0, (t)(1 << 22), (t)-2}, \ 27 | {(t)(1 << 22), (t)-(1 << 22), (t)-2}, \ 28 | {(t)(1 << 22), (t)(1 << 22), (t)-2} \ 29 | }; \ 30 | unsigned i; \ 31 | \ 32 | for (i = 0; i < sizeof(tests)/sizeof(p##_test_t); i++) { \ 33 | bool err; \ 34 | t accum = tests[i].accum0; \ 35 | assert_##ta##_eq(atomic_read_##p(&accum), \ 36 | tests[i].accum0, \ 37 | "Erroneous read, i=%u", i); \ 38 | \ 39 | assert_##ta##_eq(atomic_add_##p(&accum, tests[i].x), \ 40 | (t)((tc)tests[i].accum0 + (tc)tests[i].x), \ 41 | "i=%u, accum=%"FMT", x=%"FMT, \ 42 | i, tests[i].accum0, tests[i].x); \ 43 | assert_##ta##_eq(atomic_read_##p(&accum), accum, \ 44 | "Erroneous add, i=%u", i); \ 45 | \ 46 | accum = tests[i].accum0; \ 47 | assert_##ta##_eq(atomic_sub_##p(&accum, tests[i].x), \ 48 | (t)((tc)tests[i].accum0 - (tc)tests[i].x), \ 49 | "i=%u, accum=%"FMT", x=%"FMT, \ 50 | i, tests[i].accum0, tests[i].x); \ 51 | assert_##ta##_eq(atomic_read_##p(&accum), accum, \ 52 | "Erroneous sub, i=%u", i); \ 53 | \ 54 | accum = tests[i].accum0; \ 55 | err = atomic_cas_##p(&accum, tests[i].x, tests[i].s); \ 56 | assert_b_eq(err, tests[i].accum0 != tests[i].x, \ 57 | "Erroneous cas success/failure result"); \ 58 | assert_##ta##_eq(accum, err ? tests[i].accum0 : \ 59 | tests[i].s, "Erroneous cas effect, i=%u", i); \ 60 | \ 61 | accum = tests[i].accum0; \ 62 | atomic_write_##p(&accum, tests[i].s); \ 63 | assert_##ta##_eq(accum, tests[i].s, \ 64 | "Erroneous write, i=%u", i); \ 65 | } \ 66 | } while (0) 67 | 68 | TEST_STRUCT(uint64, uint64_t) 69 | TEST_BEGIN(test_atomic_uint64) 70 | { 71 | 72 | #if !(LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3) 73 | test_skip("64-bit atomic operations not supported"); 74 | #else 75 | TEST_BODY(uint64, uint64_t, uint64_t, u64, FMTx64); 76 | #endif 77 | } 78 | TEST_END 79 | 80 | TEST_STRUCT(uint32, uint32_t) 81 | TEST_BEGIN(test_atomic_uint32) 82 | { 83 | 84 | TEST_BODY(uint32, uint32_t, uint32_t, u32, "#"FMTx32); 85 | } 86 | TEST_END 87 | 88 | TEST_STRUCT(p, void *) 89 | TEST_BEGIN(test_atomic_p) 90 | { 91 | 92 | TEST_BODY(p, void *, uintptr_t, ptr, "p"); 93 | } 94 | TEST_END 95 | 96 | TEST_STRUCT(z, size_t) 97 | TEST_BEGIN(test_atomic_z) 98 | { 99 | 100 | TEST_BODY(z, size_t, size_t, zu, "#zx"); 101 | } 102 | TEST_END 103 | 104 | TEST_STRUCT(u, unsigned) 105 | TEST_BEGIN(test_atomic_u) 106 | { 107 | 108 | TEST_BODY(u, unsigned, unsigned, u, "#x"); 109 | } 110 | TEST_END 111 | 112 | int 113 | main(void) 114 | { 115 | 116 | return (test( 117 | test_atomic_uint64, 118 | test_atomic_uint32, 119 | test_atomic_p, 120 | test_atomic_z, 121 | test_atomic_u)); 122 | } 123 | -------------------------------------------------------------------------------- /test/integration/allocated.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | static const bool config_stats = 4 | #ifdef JEMALLOC_STATS 5 | true 6 | #else 7 | false 8 | #endif 9 | ; 10 | 11 | void * 12 | thd_start(void *arg) 13 | { 14 | int err; 15 | void *p; 16 | uint64_t a0, a1, d0, d1; 17 | uint64_t *ap0, *ap1, *dp0, *dp1; 18 | size_t sz, usize; 19 | 20 | sz = sizeof(a0); 21 | if ((err = mallctl("thread.allocated", &a0, &sz, NULL, 0))) { 22 | if (err == ENOENT) 23 | goto label_ENOENT; 24 | test_fail("%s(): Error in mallctl(): %s", __func__, 25 | strerror(err)); 26 | } 27 | sz = sizeof(ap0); 28 | if ((err = mallctl("thread.allocatedp", &ap0, &sz, NULL, 0))) { 29 | if (err == ENOENT) 30 | goto label_ENOENT; 31 | test_fail("%s(): Error in mallctl(): %s", __func__, 32 | strerror(err)); 33 | } 34 | assert_u64_eq(*ap0, a0, 35 | "\"thread.allocatedp\" should provide a pointer to internal " 36 | "storage"); 37 | 38 | sz = sizeof(d0); 39 | if ((err = mallctl("thread.deallocated", &d0, &sz, NULL, 0))) { 40 | if (err == ENOENT) 41 | goto label_ENOENT; 42 | test_fail("%s(): Error in mallctl(): %s", __func__, 43 | strerror(err)); 44 | } 45 | sz = sizeof(dp0); 46 | if ((err = mallctl("thread.deallocatedp", &dp0, &sz, NULL, 0))) { 47 | if (err == ENOENT) 48 | goto label_ENOENT; 49 | test_fail("%s(): Error in mallctl(): %s", __func__, 50 | strerror(err)); 51 | } 52 | assert_u64_eq(*dp0, d0, 53 | "\"thread.deallocatedp\" should provide a pointer to internal " 54 | "storage"); 55 | 56 | p = malloc(1); 57 | assert_ptr_not_null(p, "Unexpected malloc() error"); 58 | 59 | sz = sizeof(a1); 60 | mallctl("thread.allocated", &a1, &sz, NULL, 0); 61 | sz = sizeof(ap1); 62 | mallctl("thread.allocatedp", &ap1, &sz, NULL, 0); 63 | assert_u64_eq(*ap1, a1, 64 | "Dereferenced \"thread.allocatedp\" value should equal " 65 | "\"thread.allocated\" value"); 66 | assert_ptr_eq(ap0, ap1, 67 | "Pointer returned by \"thread.allocatedp\" should not change"); 68 | 69 | usize = malloc_usable_size(p); 70 | assert_u64_le(a0 + usize, a1, 71 | "Allocated memory counter should increase by at least the amount " 72 | "explicitly allocated"); 73 | 74 | free(p); 75 | 76 | sz = sizeof(d1); 77 | mallctl("thread.deallocated", &d1, &sz, NULL, 0); 78 | sz = sizeof(dp1); 79 | mallctl("thread.deallocatedp", &dp1, &sz, NULL, 0); 80 | assert_u64_eq(*dp1, d1, 81 | "Dereferenced \"thread.deallocatedp\" value should equal " 82 | "\"thread.deallocated\" value"); 83 | assert_ptr_eq(dp0, dp1, 84 | "Pointer returned by \"thread.deallocatedp\" should not change"); 85 | 86 | assert_u64_le(d0 + usize, d1, 87 | "Deallocated memory counter should increase by at least the amount " 88 | "explicitly deallocated"); 89 | 90 | return (NULL); 91 | label_ENOENT: 92 | assert_false(config_stats, 93 | "ENOENT should only be returned if stats are disabled"); 94 | test_skip("\"thread.allocated\" mallctl not available"); 95 | return (NULL); 96 | } 97 | 98 | TEST_BEGIN(test_main_thread) 99 | { 100 | 101 | thd_start(NULL); 102 | } 103 | TEST_END 104 | 105 | TEST_BEGIN(test_subthread) 106 | { 107 | thd_t thd; 108 | 109 | thd_create(&thd, thd_start, NULL); 110 | thd_join(thd, NULL); 111 | } 112 | TEST_END 113 | 114 | int 115 | main(void) 116 | { 117 | 118 | /* Run tests multiple times to check for bad interactions. */ 119 | return (test( 120 | test_main_thread, 121 | test_subthread, 122 | test_main_thread, 123 | test_subthread, 124 | test_main_thread)); 125 | } 126 | -------------------------------------------------------------------------------- /src/witness.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_WITNESS_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | void 5 | witness_init(witness_t *witness, const char *name, witness_rank_t rank, 6 | witness_comp_t *comp) 7 | { 8 | 9 | witness->name = name; 10 | witness->rank = rank; 11 | witness->comp = comp; 12 | } 13 | 14 | #ifdef JEMALLOC_JET 15 | #undef witness_lock_error 16 | #define witness_lock_error JEMALLOC_N(n_witness_lock_error) 17 | #endif 18 | void 19 | witness_lock_error(const witness_list_t *witnesses, const witness_t *witness) 20 | { 21 | witness_t *w; 22 | 23 | malloc_printf(": Lock rank order reversal:"); 24 | ql_foreach(w, witnesses, link) { 25 | malloc_printf(" %s(%u)", w->name, w->rank); 26 | } 27 | malloc_printf(" %s(%u)\n", witness->name, witness->rank); 28 | abort(); 29 | } 30 | #ifdef JEMALLOC_JET 31 | #undef witness_lock_error 32 | #define witness_lock_error JEMALLOC_N(witness_lock_error) 33 | witness_lock_error_t *witness_lock_error = JEMALLOC_N(n_witness_lock_error); 34 | #endif 35 | 36 | #ifdef JEMALLOC_JET 37 | #undef witness_owner_error 38 | #define witness_owner_error JEMALLOC_N(n_witness_owner_error) 39 | #endif 40 | void 41 | witness_owner_error(const witness_t *witness) 42 | { 43 | 44 | malloc_printf(": Should own %s(%u)\n", witness->name, 45 | witness->rank); 46 | abort(); 47 | } 48 | #ifdef JEMALLOC_JET 49 | #undef witness_owner_error 50 | #define witness_owner_error JEMALLOC_N(witness_owner_error) 51 | witness_owner_error_t *witness_owner_error = JEMALLOC_N(n_witness_owner_error); 52 | #endif 53 | 54 | #ifdef JEMALLOC_JET 55 | #undef witness_not_owner_error 56 | #define witness_not_owner_error JEMALLOC_N(n_witness_not_owner_error) 57 | #endif 58 | void 59 | witness_not_owner_error(const witness_t *witness) 60 | { 61 | 62 | malloc_printf(": Should not own %s(%u)\n", witness->name, 63 | witness->rank); 64 | abort(); 65 | } 66 | #ifdef JEMALLOC_JET 67 | #undef witness_not_owner_error 68 | #define witness_not_owner_error JEMALLOC_N(witness_not_owner_error) 69 | witness_not_owner_error_t *witness_not_owner_error = 70 | JEMALLOC_N(n_witness_not_owner_error); 71 | #endif 72 | 73 | #ifdef JEMALLOC_JET 74 | #undef witness_lockless_error 75 | #define witness_lockless_error JEMALLOC_N(n_witness_lockless_error) 76 | #endif 77 | void 78 | witness_lockless_error(const witness_list_t *witnesses) 79 | { 80 | witness_t *w; 81 | 82 | malloc_printf(": Should not own any locks:"); 83 | ql_foreach(w, witnesses, link) { 84 | malloc_printf(" %s(%u)", w->name, w->rank); 85 | } 86 | malloc_printf("\n"); 87 | abort(); 88 | } 89 | #ifdef JEMALLOC_JET 90 | #undef witness_lockless_error 91 | #define witness_lockless_error JEMALLOC_N(witness_lockless_error) 92 | witness_lockless_error_t *witness_lockless_error = 93 | JEMALLOC_N(n_witness_lockless_error); 94 | #endif 95 | 96 | void 97 | witnesses_cleanup(tsd_t *tsd) 98 | { 99 | 100 | witness_assert_lockless(tsd_tsdn(tsd)); 101 | 102 | /* Do nothing. */ 103 | } 104 | 105 | void 106 | witness_fork_cleanup(tsd_t *tsd) 107 | { 108 | 109 | /* Do nothing. */ 110 | } 111 | 112 | void 113 | witness_prefork(tsd_t *tsd) 114 | { 115 | 116 | tsd_witness_fork_set(tsd, true); 117 | } 118 | 119 | void 120 | witness_postfork_parent(tsd_t *tsd) 121 | { 122 | 123 | tsd_witness_fork_set(tsd, false); 124 | } 125 | 126 | void 127 | witness_postfork_child(tsd_t *tsd) 128 | { 129 | #ifndef JEMALLOC_MUTEX_INIT_CB 130 | witness_list_t *witnesses; 131 | 132 | witnesses = tsd_witnessesp_get(tsd); 133 | ql_new(witnesses); 134 | #endif 135 | tsd_witness_fork_set(tsd, false); 136 | } 137 | -------------------------------------------------------------------------------- /test/integration/aligned_alloc.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define CHUNK 0x400000 4 | #define MAXALIGN (((size_t)1) << 23) 5 | 6 | /* 7 | * On systems which can't merge extents, tests that call this function generate 8 | * a lot of dirty memory very quickly. Purging between cycles mitigates 9 | * potential OOM on e.g. 32-bit Windows. 10 | */ 11 | static void 12 | purge(void) 13 | { 14 | 15 | assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, 16 | "Unexpected mallctl error"); 17 | } 18 | 19 | TEST_BEGIN(test_alignment_errors) 20 | { 21 | size_t alignment; 22 | void *p; 23 | 24 | alignment = 0; 25 | set_errno(0); 26 | p = aligned_alloc(alignment, 1); 27 | assert_false(p != NULL || get_errno() != EINVAL, 28 | "Expected error for invalid alignment %zu", alignment); 29 | 30 | for (alignment = sizeof(size_t); alignment < MAXALIGN; 31 | alignment <<= 1) { 32 | set_errno(0); 33 | p = aligned_alloc(alignment + 1, 1); 34 | assert_false(p != NULL || get_errno() != EINVAL, 35 | "Expected error for invalid alignment %zu", 36 | alignment + 1); 37 | } 38 | } 39 | TEST_END 40 | 41 | TEST_BEGIN(test_oom_errors) 42 | { 43 | size_t alignment, size; 44 | void *p; 45 | 46 | #if LG_SIZEOF_PTR == 3 47 | alignment = UINT64_C(0x8000000000000000); 48 | size = UINT64_C(0x8000000000000000); 49 | #else 50 | alignment = 0x80000000LU; 51 | size = 0x80000000LU; 52 | #endif 53 | set_errno(0); 54 | p = aligned_alloc(alignment, size); 55 | assert_false(p != NULL || get_errno() != ENOMEM, 56 | "Expected error for aligned_alloc(%zu, %zu)", 57 | alignment, size); 58 | 59 | #if LG_SIZEOF_PTR == 3 60 | alignment = UINT64_C(0x4000000000000000); 61 | size = UINT64_C(0xc000000000000001); 62 | #else 63 | alignment = 0x40000000LU; 64 | size = 0xc0000001LU; 65 | #endif 66 | set_errno(0); 67 | p = aligned_alloc(alignment, size); 68 | assert_false(p != NULL || get_errno() != ENOMEM, 69 | "Expected error for aligned_alloc(%zu, %zu)", 70 | alignment, size); 71 | 72 | alignment = 0x10LU; 73 | #if LG_SIZEOF_PTR == 3 74 | size = UINT64_C(0xfffffffffffffff0); 75 | #else 76 | size = 0xfffffff0LU; 77 | #endif 78 | set_errno(0); 79 | p = aligned_alloc(alignment, size); 80 | assert_false(p != NULL || get_errno() != ENOMEM, 81 | "Expected error for aligned_alloc(&p, %zu, %zu)", 82 | alignment, size); 83 | } 84 | TEST_END 85 | 86 | TEST_BEGIN(test_alignment_and_size) 87 | { 88 | #define NITER 4 89 | size_t alignment, size, total; 90 | unsigned i; 91 | void *ps[NITER]; 92 | 93 | for (i = 0; i < NITER; i++) 94 | ps[i] = NULL; 95 | 96 | for (alignment = 8; 97 | alignment <= MAXALIGN; 98 | alignment <<= 1) { 99 | total = 0; 100 | for (size = 1; 101 | size < 3 * alignment && size < (1U << 31); 102 | size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { 103 | for (i = 0; i < NITER; i++) { 104 | ps[i] = aligned_alloc(alignment, size); 105 | if (ps[i] == NULL) { 106 | char buf[BUFERROR_BUF]; 107 | 108 | buferror(get_errno(), buf, sizeof(buf)); 109 | test_fail( 110 | "Error for alignment=%zu, " 111 | "size=%zu (%#zx): %s", 112 | alignment, size, size, buf); 113 | } 114 | total += malloc_usable_size(ps[i]); 115 | if (total >= (MAXALIGN << 1)) 116 | break; 117 | } 118 | for (i = 0; i < NITER; i++) { 119 | if (ps[i] != NULL) { 120 | free(ps[i]); 121 | ps[i] = NULL; 122 | } 123 | } 124 | } 125 | purge(); 126 | } 127 | #undef NITER 128 | } 129 | TEST_END 130 | 131 | int 132 | main(void) 133 | { 134 | 135 | return (test( 136 | test_alignment_errors, 137 | test_oom_errors, 138 | test_alignment_and_size)); 139 | } 140 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params1279.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file derives from SFMT 1.3.3 3 | * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was 4 | * released under the terms of the following license: 5 | * 6 | * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 7 | * University. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * * Neither the name of the Hiroshima University nor the names of 20 | * its contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | #ifndef SFMT_PARAMS1279_H 37 | #define SFMT_PARAMS1279_H 38 | 39 | #define POS1 7 40 | #define SL1 14 41 | #define SL2 3 42 | #define SR1 5 43 | #define SR2 1 44 | #define MSK1 0xf7fefffdU 45 | #define MSK2 0x7fefcfffU 46 | #define MSK3 0xaff3ef3fU 47 | #define MSK4 0xb5ffff7fU 48 | #define PARITY1 0x00000001U 49 | #define PARITY2 0x00000000U 50 | #define PARITY3 0x00000000U 51 | #define PARITY4 0x20000000U 52 | 53 | 54 | /* PARAMETERS FOR ALTIVEC */ 55 | #if defined(__APPLE__) /* For OSX */ 56 | #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) 57 | #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) 58 | #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) 59 | #define ALTI_MSK64 \ 60 | (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) 61 | #define ALTI_SL2_PERM \ 62 | (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) 63 | #define ALTI_SL2_PERM64 \ 64 | (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) 65 | #define ALTI_SR2_PERM \ 66 | (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) 67 | #define ALTI_SR2_PERM64 \ 68 | (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) 69 | #else /* For OTHER OSs(Linux?) */ 70 | #define ALTI_SL1 {SL1, SL1, SL1, SL1} 71 | #define ALTI_SR1 {SR1, SR1, SR1, SR1} 72 | #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} 73 | #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} 74 | #define ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} 75 | #define ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} 76 | #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} 77 | #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} 78 | #endif /* For OSX */ 79 | #define IDSTR "SFMT-1279:7-14-3-5-1:f7fefffd-7fefcfff-aff3ef3f-b5ffff7f" 80 | 81 | #endif /* SFMT_PARAMS1279_H */ 82 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params2281.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file derives from SFMT 1.3.3 3 | * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was 4 | * released under the terms of the following license: 5 | * 6 | * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 7 | * University. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * * Neither the name of the Hiroshima University nor the names of 20 | * its contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | #ifndef SFMT_PARAMS2281_H 37 | #define SFMT_PARAMS2281_H 38 | 39 | #define POS1 12 40 | #define SL1 19 41 | #define SL2 1 42 | #define SR1 5 43 | #define SR2 1 44 | #define MSK1 0xbff7ffbfU 45 | #define MSK2 0xfdfffffeU 46 | #define MSK3 0xf7ffef7fU 47 | #define MSK4 0xf2f7cbbfU 48 | #define PARITY1 0x00000001U 49 | #define PARITY2 0x00000000U 50 | #define PARITY3 0x00000000U 51 | #define PARITY4 0x41dfa600U 52 | 53 | 54 | /* PARAMETERS FOR ALTIVEC */ 55 | #if defined(__APPLE__) /* For OSX */ 56 | #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) 57 | #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) 58 | #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) 59 | #define ALTI_MSK64 \ 60 | (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) 61 | #define ALTI_SL2_PERM \ 62 | (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) 63 | #define ALTI_SL2_PERM64 \ 64 | (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) 65 | #define ALTI_SR2_PERM \ 66 | (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) 67 | #define ALTI_SR2_PERM64 \ 68 | (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) 69 | #else /* For OTHER OSs(Linux?) */ 70 | #define ALTI_SL1 {SL1, SL1, SL1, SL1} 71 | #define ALTI_SR1 {SR1, SR1, SR1, SR1} 72 | #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} 73 | #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} 74 | #define ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} 75 | #define ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} 76 | #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} 77 | #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} 78 | #endif /* For OSX */ 79 | #define IDSTR "SFMT-2281:12-19-1-5-1:bff7ffbf-fdfffffe-f7ffef7f-f2f7cbbf" 80 | 81 | #endif /* SFMT_PARAMS2281_H */ 82 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params4253.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file derives from SFMT 1.3.3 3 | * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was 4 | * released under the terms of the following license: 5 | * 6 | * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 7 | * University. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * * Neither the name of the Hiroshima University nor the names of 20 | * its contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | #ifndef SFMT_PARAMS4253_H 37 | #define SFMT_PARAMS4253_H 38 | 39 | #define POS1 17 40 | #define SL1 20 41 | #define SL2 1 42 | #define SR1 7 43 | #define SR2 1 44 | #define MSK1 0x9f7bffffU 45 | #define MSK2 0x9fffff5fU 46 | #define MSK3 0x3efffffbU 47 | #define MSK4 0xfffff7bbU 48 | #define PARITY1 0xa8000001U 49 | #define PARITY2 0xaf5390a3U 50 | #define PARITY3 0xb740b3f8U 51 | #define PARITY4 0x6c11486dU 52 | 53 | 54 | /* PARAMETERS FOR ALTIVEC */ 55 | #if defined(__APPLE__) /* For OSX */ 56 | #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) 57 | #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) 58 | #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) 59 | #define ALTI_MSK64 \ 60 | (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) 61 | #define ALTI_SL2_PERM \ 62 | (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) 63 | #define ALTI_SL2_PERM64 \ 64 | (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) 65 | #define ALTI_SR2_PERM \ 66 | (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) 67 | #define ALTI_SR2_PERM64 \ 68 | (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) 69 | #else /* For OTHER OSs(Linux?) */ 70 | #define ALTI_SL1 {SL1, SL1, SL1, SL1} 71 | #define ALTI_SR1 {SR1, SR1, SR1, SR1} 72 | #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} 73 | #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} 74 | #define ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} 75 | #define ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} 76 | #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} 77 | #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} 78 | #endif /* For OSX */ 79 | #define IDSTR "SFMT-4253:17-20-1-7-1:9f7bffff-9fffff5f-3efffffb-fffff7bb" 80 | 81 | #endif /* SFMT_PARAMS4253_H */ 82 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params607.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file derives from SFMT 1.3.3 3 | * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was 4 | * released under the terms of the following license: 5 | * 6 | * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 7 | * University. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * * Neither the name of the Hiroshima University nor the names of 20 | * its contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | #ifndef SFMT_PARAMS607_H 37 | #define SFMT_PARAMS607_H 38 | 39 | #define POS1 2 40 | #define SL1 15 41 | #define SL2 3 42 | #define SR1 13 43 | #define SR2 3 44 | #define MSK1 0xfdff37ffU 45 | #define MSK2 0xef7f3f7dU 46 | #define MSK3 0xff777b7dU 47 | #define MSK4 0x7ff7fb2fU 48 | #define PARITY1 0x00000001U 49 | #define PARITY2 0x00000000U 50 | #define PARITY3 0x00000000U 51 | #define PARITY4 0x5986f054U 52 | 53 | 54 | /* PARAMETERS FOR ALTIVEC */ 55 | #if defined(__APPLE__) /* For OSX */ 56 | #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) 57 | #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) 58 | #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) 59 | #define ALTI_MSK64 \ 60 | (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) 61 | #define ALTI_SL2_PERM \ 62 | (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) 63 | #define ALTI_SL2_PERM64 \ 64 | (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) 65 | #define ALTI_SR2_PERM \ 66 | (vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12) 67 | #define ALTI_SR2_PERM64 \ 68 | (vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12) 69 | #else /* For OTHER OSs(Linux?) */ 70 | #define ALTI_SL1 {SL1, SL1, SL1, SL1} 71 | #define ALTI_SR1 {SR1, SR1, SR1, SR1} 72 | #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} 73 | #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} 74 | #define ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} 75 | #define ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} 76 | #define ALTI_SR2_PERM {5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12} 77 | #define ALTI_SR2_PERM64 {13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12} 78 | #endif /* For OSX */ 79 | #define IDSTR "SFMT-607:2-15-3-13-3:fdff37ff-ef7f3f7d-ff777b7d-7ff7fb2f" 80 | 81 | #endif /* SFMT_PARAMS607_H */ 82 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params19937.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file derives from SFMT 1.3.3 3 | * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was 4 | * released under the terms of the following license: 5 | * 6 | * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 7 | * University. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * * Neither the name of the Hiroshima University nor the names of 20 | * its contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | #ifndef SFMT_PARAMS19937_H 37 | #define SFMT_PARAMS19937_H 38 | 39 | #define POS1 122 40 | #define SL1 18 41 | #define SL2 1 42 | #define SR1 11 43 | #define SR2 1 44 | #define MSK1 0xdfffffefU 45 | #define MSK2 0xddfecb7fU 46 | #define MSK3 0xbffaffffU 47 | #define MSK4 0xbffffff6U 48 | #define PARITY1 0x00000001U 49 | #define PARITY2 0x00000000U 50 | #define PARITY3 0x00000000U 51 | #define PARITY4 0x13c9e684U 52 | 53 | 54 | /* PARAMETERS FOR ALTIVEC */ 55 | #if defined(__APPLE__) /* For OSX */ 56 | #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) 57 | #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) 58 | #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) 59 | #define ALTI_MSK64 \ 60 | (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) 61 | #define ALTI_SL2_PERM \ 62 | (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) 63 | #define ALTI_SL2_PERM64 \ 64 | (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) 65 | #define ALTI_SR2_PERM \ 66 | (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) 67 | #define ALTI_SR2_PERM64 \ 68 | (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) 69 | #else /* For OTHER OSs(Linux?) */ 70 | #define ALTI_SL1 {SL1, SL1, SL1, SL1} 71 | #define ALTI_SR1 {SR1, SR1, SR1, SR1} 72 | #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} 73 | #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} 74 | #define ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} 75 | #define ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} 76 | #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} 77 | #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} 78 | #endif /* For OSX */ 79 | #define IDSTR "SFMT-19937:122-18-1-11-1:dfffffef-ddfecb7f-bffaffff-bffffff6" 80 | 81 | #endif /* SFMT_PARAMS19937_H */ 82 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params11213.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file derives from SFMT 1.3.3 3 | * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was 4 | * released under the terms of the following license: 5 | * 6 | * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 7 | * University. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * * Neither the name of the Hiroshima University nor the names of 20 | * its contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | #ifndef SFMT_PARAMS11213_H 37 | #define SFMT_PARAMS11213_H 38 | 39 | #define POS1 68 40 | #define SL1 14 41 | #define SL2 3 42 | #define SR1 7 43 | #define SR2 3 44 | #define MSK1 0xeffff7fbU 45 | #define MSK2 0xffffffefU 46 | #define MSK3 0xdfdfbfffU 47 | #define MSK4 0x7fffdbfdU 48 | #define PARITY1 0x00000001U 49 | #define PARITY2 0x00000000U 50 | #define PARITY3 0xe8148000U 51 | #define PARITY4 0xd0c7afa3U 52 | 53 | 54 | /* PARAMETERS FOR ALTIVEC */ 55 | #if defined(__APPLE__) /* For OSX */ 56 | #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) 57 | #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) 58 | #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) 59 | #define ALTI_MSK64 \ 60 | (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) 61 | #define ALTI_SL2_PERM \ 62 | (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) 63 | #define ALTI_SL2_PERM64 \ 64 | (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) 65 | #define ALTI_SR2_PERM \ 66 | (vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12) 67 | #define ALTI_SR2_PERM64 \ 68 | (vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12) 69 | #else /* For OTHER OSs(Linux?) */ 70 | #define ALTI_SL1 {SL1, SL1, SL1, SL1} 71 | #define ALTI_SR1 {SR1, SR1, SR1, SR1} 72 | #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} 73 | #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} 74 | #define ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} 75 | #define ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} 76 | #define ALTI_SR2_PERM {5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12} 77 | #define ALTI_SR2_PERM64 {13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12} 78 | #endif /* For OSX */ 79 | #define IDSTR "SFMT-11213:68-14-3-7-3:effff7fb-ffffffef-dfdfbfff-7fffdbfd" 80 | 81 | #endif /* SFMT_PARAMS11213_H */ 82 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params132049.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file derives from SFMT 1.3.3 3 | * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was 4 | * released under the terms of the following license: 5 | * 6 | * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 7 | * University. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * * Neither the name of the Hiroshima University nor the names of 20 | * its contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | #ifndef SFMT_PARAMS132049_H 37 | #define SFMT_PARAMS132049_H 38 | 39 | #define POS1 110 40 | #define SL1 19 41 | #define SL2 1 42 | #define SR1 21 43 | #define SR2 1 44 | #define MSK1 0xffffbb5fU 45 | #define MSK2 0xfb6ebf95U 46 | #define MSK3 0xfffefffaU 47 | #define MSK4 0xcff77fffU 48 | #define PARITY1 0x00000001U 49 | #define PARITY2 0x00000000U 50 | #define PARITY3 0xcb520000U 51 | #define PARITY4 0xc7e91c7dU 52 | 53 | 54 | /* PARAMETERS FOR ALTIVEC */ 55 | #if defined(__APPLE__) /* For OSX */ 56 | #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) 57 | #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) 58 | #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) 59 | #define ALTI_MSK64 \ 60 | (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) 61 | #define ALTI_SL2_PERM \ 62 | (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) 63 | #define ALTI_SL2_PERM64 \ 64 | (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) 65 | #define ALTI_SR2_PERM \ 66 | (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) 67 | #define ALTI_SR2_PERM64 \ 68 | (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) 69 | #else /* For OTHER OSs(Linux?) */ 70 | #define ALTI_SL1 {SL1, SL1, SL1, SL1} 71 | #define ALTI_SR1 {SR1, SR1, SR1, SR1} 72 | #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} 73 | #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} 74 | #define ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} 75 | #define ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} 76 | #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} 77 | #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} 78 | #endif /* For OSX */ 79 | #define IDSTR "SFMT-132049:110-19-1-21-1:ffffbb5f-fb6ebf95-fffefffa-cff77fff" 80 | 81 | #endif /* SFMT_PARAMS132049_H */ 82 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params44497.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file derives from SFMT 1.3.3 3 | * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was 4 | * released under the terms of the following license: 5 | * 6 | * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 7 | * University. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * * Neither the name of the Hiroshima University nor the names of 20 | * its contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | #ifndef SFMT_PARAMS44497_H 37 | #define SFMT_PARAMS44497_H 38 | 39 | #define POS1 330 40 | #define SL1 5 41 | #define SL2 3 42 | #define SR1 9 43 | #define SR2 3 44 | #define MSK1 0xeffffffbU 45 | #define MSK2 0xdfbebfffU 46 | #define MSK3 0xbfbf7befU 47 | #define MSK4 0x9ffd7bffU 48 | #define PARITY1 0x00000001U 49 | #define PARITY2 0x00000000U 50 | #define PARITY3 0xa3ac4000U 51 | #define PARITY4 0xecc1327aU 52 | 53 | 54 | /* PARAMETERS FOR ALTIVEC */ 55 | #if defined(__APPLE__) /* For OSX */ 56 | #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) 57 | #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) 58 | #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) 59 | #define ALTI_MSK64 \ 60 | (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) 61 | #define ALTI_SL2_PERM \ 62 | (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) 63 | #define ALTI_SL2_PERM64 \ 64 | (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) 65 | #define ALTI_SR2_PERM \ 66 | (vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12) 67 | #define ALTI_SR2_PERM64 \ 68 | (vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12) 69 | #else /* For OTHER OSs(Linux?) */ 70 | #define ALTI_SL1 {SL1, SL1, SL1, SL1} 71 | #define ALTI_SR1 {SR1, SR1, SR1, SR1} 72 | #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} 73 | #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} 74 | #define ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} 75 | #define ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} 76 | #define ALTI_SR2_PERM {5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12} 77 | #define ALTI_SR2_PERM64 {13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12} 78 | #endif /* For OSX */ 79 | #define IDSTR "SFMT-44497:330-5-3-9-3:effffffb-dfbebfff-bfbf7bef-9ffd7bff" 80 | 81 | #endif /* SFMT_PARAMS44497_H */ 82 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params86243.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file derives from SFMT 1.3.3 3 | * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was 4 | * released under the terms of the following license: 5 | * 6 | * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 7 | * University. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * * Neither the name of the Hiroshima University nor the names of 20 | * its contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | #ifndef SFMT_PARAMS86243_H 37 | #define SFMT_PARAMS86243_H 38 | 39 | #define POS1 366 40 | #define SL1 6 41 | #define SL2 7 42 | #define SR1 19 43 | #define SR2 1 44 | #define MSK1 0xfdbffbffU 45 | #define MSK2 0xbff7ff3fU 46 | #define MSK3 0xfd77efffU 47 | #define MSK4 0xbf9ff3ffU 48 | #define PARITY1 0x00000001U 49 | #define PARITY2 0x00000000U 50 | #define PARITY3 0x00000000U 51 | #define PARITY4 0xe9528d85U 52 | 53 | 54 | /* PARAMETERS FOR ALTIVEC */ 55 | #if defined(__APPLE__) /* For OSX */ 56 | #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) 57 | #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) 58 | #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) 59 | #define ALTI_MSK64 \ 60 | (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) 61 | #define ALTI_SL2_PERM \ 62 | (vector unsigned char)(25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6) 63 | #define ALTI_SL2_PERM64 \ 64 | (vector unsigned char)(7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6) 65 | #define ALTI_SR2_PERM \ 66 | (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) 67 | #define ALTI_SR2_PERM64 \ 68 | (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) 69 | #else /* For OTHER OSs(Linux?) */ 70 | #define ALTI_SL1 {SL1, SL1, SL1, SL1} 71 | #define ALTI_SR1 {SR1, SR1, SR1, SR1} 72 | #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} 73 | #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} 74 | #define ALTI_SL2_PERM {25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6} 75 | #define ALTI_SL2_PERM64 {7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6} 76 | #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} 77 | #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} 78 | #endif /* For OSX */ 79 | #define IDSTR "SFMT-86243:366-6-7-19-1:fdbffbff-bff7ff3f-fd77efff-bf9ff3ff" 80 | 81 | #endif /* SFMT_PARAMS86243_H */ 82 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params216091.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file derives from SFMT 1.3.3 3 | * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was 4 | * released under the terms of the following license: 5 | * 6 | * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 7 | * University. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * * Neither the name of the Hiroshima University nor the names of 20 | * its contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | #ifndef SFMT_PARAMS216091_H 37 | #define SFMT_PARAMS216091_H 38 | 39 | #define POS1 627 40 | #define SL1 11 41 | #define SL2 3 42 | #define SR1 10 43 | #define SR2 1 44 | #define MSK1 0xbff7bff7U 45 | #define MSK2 0xbfffffffU 46 | #define MSK3 0xbffffa7fU 47 | #define MSK4 0xffddfbfbU 48 | #define PARITY1 0xf8000001U 49 | #define PARITY2 0x89e80709U 50 | #define PARITY3 0x3bd2b64bU 51 | #define PARITY4 0x0c64b1e4U 52 | 53 | 54 | /* PARAMETERS FOR ALTIVEC */ 55 | #if defined(__APPLE__) /* For OSX */ 56 | #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) 57 | #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) 58 | #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) 59 | #define ALTI_MSK64 \ 60 | (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) 61 | #define ALTI_SL2_PERM \ 62 | (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) 63 | #define ALTI_SL2_PERM64 \ 64 | (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) 65 | #define ALTI_SR2_PERM \ 66 | (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) 67 | #define ALTI_SR2_PERM64 \ 68 | (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) 69 | #else /* For OTHER OSs(Linux?) */ 70 | #define ALTI_SL1 {SL1, SL1, SL1, SL1} 71 | #define ALTI_SR1 {SR1, SR1, SR1, SR1} 72 | #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} 73 | #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} 74 | #define ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} 75 | #define ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} 76 | #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} 77 | #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} 78 | #endif /* For OSX */ 79 | #define IDSTR "SFMT-216091:627-11-3-10-1:bff7bff7-bfffffff-bffffa7f-ffddfbfb" 80 | 81 | #endif /* SFMT_PARAMS216091_H */ 82 | -------------------------------------------------------------------------------- /test/unit/prof_thread_name.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #ifdef JEMALLOC_PROF 4 | const char *malloc_conf = "prof:true,prof_active:false"; 5 | #endif 6 | 7 | static void 8 | mallctl_thread_name_get_impl(const char *thread_name_expected, const char *func, 9 | int line) 10 | { 11 | const char *thread_name_old; 12 | size_t sz; 13 | 14 | sz = sizeof(thread_name_old); 15 | assert_d_eq(mallctl("thread.prof.name", &thread_name_old, &sz, NULL, 0), 16 | 0, "%s():%d: Unexpected mallctl failure reading thread.prof.name", 17 | func, line); 18 | assert_str_eq(thread_name_old, thread_name_expected, 19 | "%s():%d: Unexpected thread.prof.name value", func, line); 20 | } 21 | #define mallctl_thread_name_get(a) \ 22 | mallctl_thread_name_get_impl(a, __func__, __LINE__) 23 | 24 | static void 25 | mallctl_thread_name_set_impl(const char *thread_name, const char *func, 26 | int line) 27 | { 28 | 29 | assert_d_eq(mallctl("thread.prof.name", NULL, NULL, &thread_name, 30 | sizeof(thread_name)), 0, 31 | "%s():%d: Unexpected mallctl failure reading thread.prof.name", 32 | func, line); 33 | mallctl_thread_name_get_impl(thread_name, func, line); 34 | } 35 | #define mallctl_thread_name_set(a) \ 36 | mallctl_thread_name_set_impl(a, __func__, __LINE__) 37 | 38 | TEST_BEGIN(test_prof_thread_name_validation) 39 | { 40 | const char *thread_name; 41 | 42 | test_skip_if(!config_prof); 43 | 44 | mallctl_thread_name_get(""); 45 | mallctl_thread_name_set("hi there"); 46 | 47 | /* NULL input shouldn't be allowed. */ 48 | thread_name = NULL; 49 | assert_d_eq(mallctl("thread.prof.name", NULL, NULL, &thread_name, 50 | sizeof(thread_name)), EFAULT, 51 | "Unexpected mallctl result writing \"%s\" to thread.prof.name", 52 | thread_name); 53 | 54 | /* '\n' shouldn't be allowed. */ 55 | thread_name = "hi\nthere"; 56 | assert_d_eq(mallctl("thread.prof.name", NULL, NULL, &thread_name, 57 | sizeof(thread_name)), EFAULT, 58 | "Unexpected mallctl result writing \"%s\" to thread.prof.name", 59 | thread_name); 60 | 61 | /* Simultaneous read/write shouldn't be allowed. */ 62 | { 63 | const char *thread_name_old; 64 | size_t sz; 65 | 66 | sz = sizeof(thread_name_old); 67 | assert_d_eq(mallctl("thread.prof.name", &thread_name_old, &sz, 68 | &thread_name, sizeof(thread_name)), EPERM, 69 | "Unexpected mallctl result writing \"%s\" to " 70 | "thread.prof.name", thread_name); 71 | } 72 | 73 | mallctl_thread_name_set(""); 74 | } 75 | TEST_END 76 | 77 | #define NTHREADS 4 78 | #define NRESET 25 79 | static void * 80 | thd_start(void *varg) 81 | { 82 | unsigned thd_ind = *(unsigned *)varg; 83 | char thread_name[16] = ""; 84 | unsigned i; 85 | 86 | malloc_snprintf(thread_name, sizeof(thread_name), "thread %u", thd_ind); 87 | 88 | mallctl_thread_name_get(""); 89 | mallctl_thread_name_set(thread_name); 90 | 91 | for (i = 0; i < NRESET; i++) { 92 | assert_d_eq(mallctl("prof.reset", NULL, NULL, NULL, 0), 0, 93 | "Unexpected error while resetting heap profile data"); 94 | mallctl_thread_name_get(thread_name); 95 | } 96 | 97 | mallctl_thread_name_set(thread_name); 98 | mallctl_thread_name_set(""); 99 | 100 | return (NULL); 101 | } 102 | 103 | TEST_BEGIN(test_prof_thread_name_threaded) 104 | { 105 | thd_t thds[NTHREADS]; 106 | unsigned thd_args[NTHREADS]; 107 | unsigned i; 108 | 109 | test_skip_if(!config_prof); 110 | 111 | for (i = 0; i < NTHREADS; i++) { 112 | thd_args[i] = i; 113 | thd_create(&thds[i], thd_start, (void *)&thd_args[i]); 114 | } 115 | for (i = 0; i < NTHREADS; i++) 116 | thd_join(thds[i], NULL); 117 | } 118 | TEST_END 119 | #undef NTHREADS 120 | #undef NRESET 121 | 122 | int 123 | main(void) 124 | { 125 | 126 | return (test( 127 | test_prof_thread_name_validation, 128 | test_prof_thread_name_threaded)); 129 | } 130 | -------------------------------------------------------------------------------- /include/jemalloc/jemalloc_macros.h.in: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define JEMALLOC_VERSION "@jemalloc_version@" 8 | #define JEMALLOC_VERSION_MAJOR @jemalloc_version_major@ 9 | #define JEMALLOC_VERSION_MINOR @jemalloc_version_minor@ 10 | #define JEMALLOC_VERSION_BUGFIX @jemalloc_version_bugfix@ 11 | #define JEMALLOC_VERSION_NREV @jemalloc_version_nrev@ 12 | #define JEMALLOC_VERSION_GID "@jemalloc_version_gid@" 13 | 14 | # define MALLOCX_LG_ALIGN(la) ((int)(la)) 15 | # if LG_SIZEOF_PTR == 2 16 | # define MALLOCX_ALIGN(a) ((int)(ffs((int)(a))-1)) 17 | # else 18 | # define MALLOCX_ALIGN(a) \ 19 | ((int)(((size_t)(a) < (size_t)INT_MAX) ? ffs((int)(a))-1 : \ 20 | ffs((int)(((size_t)(a))>>32))+31)) 21 | # endif 22 | # define MALLOCX_ZERO ((int)0x40) 23 | /* 24 | * Bias tcache index bits so that 0 encodes "automatic tcache management", and 1 25 | * encodes MALLOCX_TCACHE_NONE. 26 | */ 27 | # define MALLOCX_TCACHE(tc) ((int)(((tc)+2) << 8)) 28 | # define MALLOCX_TCACHE_NONE MALLOCX_TCACHE(-1) 29 | /* 30 | * Bias arena index bits so that 0 encodes "use an automatically chosen arena". 31 | */ 32 | # define MALLOCX_ARENA(a) ((((int)(a))+1) << 20) 33 | 34 | #if defined(__cplusplus) && defined(JEMALLOC_USE_CXX_THROW) 35 | # define JEMALLOC_CXX_THROW throw() 36 | #else 37 | # define JEMALLOC_CXX_THROW 38 | #endif 39 | 40 | #if _MSC_VER 41 | # define JEMALLOC_ATTR(s) 42 | # define JEMALLOC_ALIGNED(s) __declspec(align(s)) 43 | # define JEMALLOC_ALLOC_SIZE(s) 44 | # define JEMALLOC_ALLOC_SIZE2(s1, s2) 45 | # ifndef JEMALLOC_EXPORT 46 | # ifdef DLLEXPORT 47 | # define JEMALLOC_EXPORT __declspec(dllexport) 48 | # else 49 | # define JEMALLOC_EXPORT __declspec(dllimport) 50 | # endif 51 | # endif 52 | # define JEMALLOC_FORMAT_PRINTF(s, i) 53 | # define JEMALLOC_NOINLINE __declspec(noinline) 54 | # ifdef __cplusplus 55 | # define JEMALLOC_NOTHROW __declspec(nothrow) 56 | # else 57 | # define JEMALLOC_NOTHROW 58 | # endif 59 | # define JEMALLOC_SECTION(s) __declspec(allocate(s)) 60 | # define JEMALLOC_RESTRICT_RETURN __declspec(restrict) 61 | # if _MSC_VER >= 1900 && !defined(__EDG__) 62 | # define JEMALLOC_ALLOCATOR __declspec(allocator) 63 | # else 64 | # define JEMALLOC_ALLOCATOR 65 | # endif 66 | #elif defined(JEMALLOC_HAVE_ATTR) 67 | # define JEMALLOC_ATTR(s) __attribute__((s)) 68 | # define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s)) 69 | # ifdef JEMALLOC_HAVE_ATTR_ALLOC_SIZE 70 | # define JEMALLOC_ALLOC_SIZE(s) JEMALLOC_ATTR(alloc_size(s)) 71 | # define JEMALLOC_ALLOC_SIZE2(s1, s2) JEMALLOC_ATTR(alloc_size(s1, s2)) 72 | # else 73 | # define JEMALLOC_ALLOC_SIZE(s) 74 | # define JEMALLOC_ALLOC_SIZE2(s1, s2) 75 | # endif 76 | # ifndef JEMALLOC_EXPORT 77 | # define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default")) 78 | # endif 79 | # ifdef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF 80 | # define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(gnu_printf, s, i)) 81 | # elif defined(JEMALLOC_HAVE_ATTR_FORMAT_PRINTF) 82 | # define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(printf, s, i)) 83 | # else 84 | # define JEMALLOC_FORMAT_PRINTF(s, i) 85 | # endif 86 | # define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline) 87 | # define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow) 88 | # define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s)) 89 | # define JEMALLOC_RESTRICT_RETURN 90 | # define JEMALLOC_ALLOCATOR 91 | #else 92 | # define JEMALLOC_ATTR(s) 93 | # define JEMALLOC_ALIGNED(s) 94 | # define JEMALLOC_ALLOC_SIZE(s) 95 | # define JEMALLOC_ALLOC_SIZE2(s1, s2) 96 | # define JEMALLOC_EXPORT 97 | # define JEMALLOC_FORMAT_PRINTF(s, i) 98 | # define JEMALLOC_NOINLINE 99 | # define JEMALLOC_NOTHROW 100 | # define JEMALLOC_SECTION(s) 101 | # define JEMALLOC_RESTRICT_RETURN 102 | # define JEMALLOC_ALLOCATOR 103 | #endif 104 | -------------------------------------------------------------------------------- /include/jemalloc/internal/ctl.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | typedef struct ctl_node_s ctl_node_t; 5 | typedef struct ctl_named_node_s ctl_named_node_t; 6 | typedef struct ctl_indexed_node_s ctl_indexed_node_t; 7 | typedef struct ctl_arena_stats_s ctl_arena_stats_t; 8 | typedef struct ctl_stats_s ctl_stats_t; 9 | 10 | #endif /* JEMALLOC_H_TYPES */ 11 | /******************************************************************************/ 12 | #ifdef JEMALLOC_H_STRUCTS 13 | 14 | struct ctl_node_s { 15 | bool named; 16 | }; 17 | 18 | struct ctl_named_node_s { 19 | struct ctl_node_s node; 20 | const char *name; 21 | /* If (nchildren == 0), this is a terminal node. */ 22 | unsigned nchildren; 23 | const ctl_node_t *children; 24 | int (*ctl)(tsd_t *, const size_t *, size_t, void *, 25 | size_t *, void *, size_t); 26 | }; 27 | 28 | struct ctl_indexed_node_s { 29 | struct ctl_node_s node; 30 | const ctl_named_node_t *(*index)(tsdn_t *, const size_t *, size_t, 31 | size_t); 32 | }; 33 | 34 | struct ctl_arena_stats_s { 35 | bool initialized; 36 | unsigned nthreads; 37 | const char *dss; 38 | ssize_t lg_dirty_mult; 39 | ssize_t decay_time; 40 | size_t pactive; 41 | size_t pdirty; 42 | 43 | /* The remainder are only populated if config_stats is true. */ 44 | 45 | arena_stats_t astats; 46 | 47 | /* Aggregate stats for small size classes, based on bin stats. */ 48 | size_t allocated_small; 49 | uint64_t nmalloc_small; 50 | uint64_t ndalloc_small; 51 | uint64_t nrequests_small; 52 | 53 | malloc_bin_stats_t bstats[NBINS]; 54 | malloc_large_stats_t *lstats; /* nlclasses elements. */ 55 | malloc_huge_stats_t *hstats; /* nhclasses elements. */ 56 | }; 57 | 58 | struct ctl_stats_s { 59 | size_t allocated; 60 | size_t active; 61 | size_t metadata; 62 | size_t resident; 63 | size_t mapped; 64 | size_t retained; 65 | unsigned narenas; 66 | ctl_arena_stats_t *arenas; /* (narenas + 1) elements. */ 67 | }; 68 | 69 | #endif /* JEMALLOC_H_STRUCTS */ 70 | /******************************************************************************/ 71 | #ifdef JEMALLOC_H_EXTERNS 72 | 73 | int ctl_byname(tsd_t *tsd, const char *name, void *oldp, size_t *oldlenp, 74 | void *newp, size_t newlen); 75 | int ctl_nametomib(tsdn_t *tsdn, const char *name, size_t *mibp, 76 | size_t *miblenp); 77 | 78 | int ctl_bymib(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, 79 | size_t *oldlenp, void *newp, size_t newlen); 80 | bool ctl_boot(void); 81 | void ctl_prefork(tsdn_t *tsdn); 82 | void ctl_postfork_parent(tsdn_t *tsdn); 83 | void ctl_postfork_child(tsdn_t *tsdn); 84 | 85 | #define xmallctl(name, oldp, oldlenp, newp, newlen) do { \ 86 | if (je_mallctl(name, oldp, oldlenp, newp, newlen) \ 87 | != 0) { \ 88 | malloc_printf( \ 89 | ": Failure in xmallctl(\"%s\", ...)\n", \ 90 | name); \ 91 | abort(); \ 92 | } \ 93 | } while (0) 94 | 95 | #define xmallctlnametomib(name, mibp, miblenp) do { \ 96 | if (je_mallctlnametomib(name, mibp, miblenp) != 0) { \ 97 | malloc_printf(": Failure in " \ 98 | "xmallctlnametomib(\"%s\", ...)\n", name); \ 99 | abort(); \ 100 | } \ 101 | } while (0) 102 | 103 | #define xmallctlbymib(mib, miblen, oldp, oldlenp, newp, newlen) do { \ 104 | if (je_mallctlbymib(mib, miblen, oldp, oldlenp, newp, \ 105 | newlen) != 0) { \ 106 | malloc_write( \ 107 | ": Failure in xmallctlbymib()\n"); \ 108 | abort(); \ 109 | } \ 110 | } while (0) 111 | 112 | #endif /* JEMALLOC_H_EXTERNS */ 113 | /******************************************************************************/ 114 | #ifdef JEMALLOC_H_INLINES 115 | 116 | #endif /* JEMALLOC_H_INLINES */ 117 | /******************************************************************************/ 118 | 119 | -------------------------------------------------------------------------------- /src/rtree.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_RTREE_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | static unsigned 5 | hmin(unsigned ha, unsigned hb) 6 | { 7 | 8 | return (ha < hb ? ha : hb); 9 | } 10 | 11 | /* Only the most significant bits of keys passed to rtree_[gs]et() are used. */ 12 | bool 13 | rtree_new(rtree_t *rtree, unsigned bits, rtree_node_alloc_t *alloc, 14 | rtree_node_dalloc_t *dalloc) 15 | { 16 | unsigned bits_in_leaf, height, i; 17 | 18 | assert(RTREE_HEIGHT_MAX == ((ZU(1) << (LG_SIZEOF_PTR+3)) / 19 | RTREE_BITS_PER_LEVEL)); 20 | assert(bits > 0 && bits <= (sizeof(uintptr_t) << 3)); 21 | 22 | bits_in_leaf = (bits % RTREE_BITS_PER_LEVEL) == 0 ? RTREE_BITS_PER_LEVEL 23 | : (bits % RTREE_BITS_PER_LEVEL); 24 | if (bits > bits_in_leaf) { 25 | height = 1 + (bits - bits_in_leaf) / RTREE_BITS_PER_LEVEL; 26 | if ((height-1) * RTREE_BITS_PER_LEVEL + bits_in_leaf != bits) 27 | height++; 28 | } else 29 | height = 1; 30 | assert((height-1) * RTREE_BITS_PER_LEVEL + bits_in_leaf == bits); 31 | 32 | rtree->alloc = alloc; 33 | rtree->dalloc = dalloc; 34 | rtree->height = height; 35 | 36 | /* Root level. */ 37 | rtree->levels[0].subtree = NULL; 38 | rtree->levels[0].bits = (height > 1) ? RTREE_BITS_PER_LEVEL : 39 | bits_in_leaf; 40 | rtree->levels[0].cumbits = rtree->levels[0].bits; 41 | /* Interior levels. */ 42 | for (i = 1; i < height-1; i++) { 43 | rtree->levels[i].subtree = NULL; 44 | rtree->levels[i].bits = RTREE_BITS_PER_LEVEL; 45 | rtree->levels[i].cumbits = rtree->levels[i-1].cumbits + 46 | RTREE_BITS_PER_LEVEL; 47 | } 48 | /* Leaf level. */ 49 | if (height > 1) { 50 | rtree->levels[height-1].subtree = NULL; 51 | rtree->levels[height-1].bits = bits_in_leaf; 52 | rtree->levels[height-1].cumbits = bits; 53 | } 54 | 55 | /* Compute lookup table to be used by rtree_start_level(). */ 56 | for (i = 0; i < RTREE_HEIGHT_MAX; i++) { 57 | rtree->start_level[i] = hmin(RTREE_HEIGHT_MAX - 1 - i, height - 58 | 1); 59 | } 60 | 61 | return (false); 62 | } 63 | 64 | static void 65 | rtree_delete_subtree(rtree_t *rtree, rtree_node_elm_t *node, unsigned level) 66 | { 67 | 68 | if (level + 1 < rtree->height) { 69 | size_t nchildren, i; 70 | 71 | nchildren = ZU(1) << rtree->levels[level].bits; 72 | for (i = 0; i < nchildren; i++) { 73 | rtree_node_elm_t *child = node[i].child; 74 | if (child != NULL) 75 | rtree_delete_subtree(rtree, child, level + 1); 76 | } 77 | } 78 | rtree->dalloc(node); 79 | } 80 | 81 | void 82 | rtree_delete(rtree_t *rtree) 83 | { 84 | unsigned i; 85 | 86 | for (i = 0; i < rtree->height; i++) { 87 | rtree_node_elm_t *subtree = rtree->levels[i].subtree; 88 | if (subtree != NULL) 89 | rtree_delete_subtree(rtree, subtree, i); 90 | } 91 | } 92 | 93 | static rtree_node_elm_t * 94 | rtree_node_init(rtree_t *rtree, unsigned level, rtree_node_elm_t **elmp) 95 | { 96 | rtree_node_elm_t *node; 97 | 98 | if (atomic_cas_p((void **)elmp, NULL, RTREE_NODE_INITIALIZING)) { 99 | spin_t spinner; 100 | 101 | /* 102 | * Another thread is already in the process of initializing. 103 | * Spin-wait until initialization is complete. 104 | */ 105 | spin_init(&spinner); 106 | do { 107 | spin_adaptive(&spinner); 108 | node = atomic_read_p((void **)elmp); 109 | } while (node == RTREE_NODE_INITIALIZING); 110 | } else { 111 | node = rtree->alloc(ZU(1) << rtree->levels[level].bits); 112 | if (node == NULL) 113 | return (NULL); 114 | atomic_write_p((void **)elmp, node); 115 | } 116 | 117 | return (node); 118 | } 119 | 120 | rtree_node_elm_t * 121 | rtree_subtree_read_hard(rtree_t *rtree, unsigned level) 122 | { 123 | 124 | return (rtree_node_init(rtree, level, &rtree->levels[level].subtree)); 125 | } 126 | 127 | rtree_node_elm_t * 128 | rtree_child_read_hard(rtree_t *rtree, rtree_node_elm_t *elm, unsigned level) 129 | { 130 | 131 | return (rtree_node_init(rtree, level+1, &elm->child)); 132 | } 133 | -------------------------------------------------------------------------------- /include/jemalloc/internal/smoothstep.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Generate a discrete lookup table for a sigmoid function in the smoothstep 4 | # family (https://en.wikipedia.org/wiki/Smoothstep), where the lookup table 5 | # entries correspond to x in [1/nsteps, 2/nsteps, ..., nsteps/nsteps]. Encode 6 | # the entries using a binary fixed point representation. 7 | # 8 | # Usage: smoothstep.sh 9 | # 10 | # is in {smooth, smoother, smoothest}. 11 | # must be greater than zero. 12 | # must be in [0..62]; reasonable values are roughly [10..30]. 13 | # is x decimal precision. 14 | # is y decimal precision. 15 | 16 | #set -x 17 | 18 | cmd="sh smoothstep.sh $*" 19 | variant=$1 20 | nsteps=$2 21 | bfp=$3 22 | xprec=$4 23 | yprec=$5 24 | 25 | case "${variant}" in 26 | smooth) 27 | ;; 28 | smoother) 29 | ;; 30 | smoothest) 31 | ;; 32 | *) 33 | echo "Unsupported variant" 34 | exit 1 35 | ;; 36 | esac 37 | 38 | smooth() { 39 | step=$1 40 | y=`echo ${yprec} k ${step} ${nsteps} / sx _2 lx 3 ^ '*' 3 lx 2 ^ '*' + p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g'` 41 | h=`echo ${yprec} k 2 ${bfp} ^ ${y} '*' p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g' | tr '.' ' ' | awk '{print $1}' ` 42 | } 43 | 44 | smoother() { 45 | step=$1 46 | y=`echo ${yprec} k ${step} ${nsteps} / sx 6 lx 5 ^ '*' _15 lx 4 ^ '*' + 10 lx 3 ^ '*' + p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g'` 47 | h=`echo ${yprec} k 2 ${bfp} ^ ${y} '*' p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g' | tr '.' ' ' | awk '{print $1}' ` 48 | } 49 | 50 | smoothest() { 51 | step=$1 52 | y=`echo ${yprec} k ${step} ${nsteps} / sx _20 lx 7 ^ '*' 70 lx 6 ^ '*' + _84 lx 5 ^ '*' + 35 lx 4 ^ '*' + p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g'` 53 | h=`echo ${yprec} k 2 ${bfp} ^ ${y} '*' p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g' | tr '.' ' ' | awk '{print $1}' ` 54 | } 55 | 56 | cat < NHUGE ? NHUGE : get_nhuge(); 103 | nptrs = nsmall + nlarge + nhuge; 104 | ptrs = (void **)malloc(nptrs * sizeof(void *)); 105 | assert_ptr_not_null(ptrs, "Unexpected malloc() failure"); 106 | 107 | /* Allocate objects with a wide range of sizes. */ 108 | for (i = 0; i < nsmall; i++) { 109 | sz = get_small_size(i); 110 | ptrs[i] = mallocx(sz, flags); 111 | assert_ptr_not_null(ptrs[i], 112 | "Unexpected mallocx(%zu, %#x) failure", sz, flags); 113 | } 114 | for (i = 0; i < nlarge; i++) { 115 | sz = get_large_size(i); 116 | ptrs[nsmall + i] = mallocx(sz, flags); 117 | assert_ptr_not_null(ptrs[i], 118 | "Unexpected mallocx(%zu, %#x) failure", sz, flags); 119 | } 120 | for (i = 0; i < nhuge; i++) { 121 | sz = get_huge_size(i); 122 | ptrs[nsmall + nlarge + i] = mallocx(sz, flags); 123 | assert_ptr_not_null(ptrs[i], 124 | "Unexpected mallocx(%zu, %#x) failure", sz, flags); 125 | } 126 | 127 | tsdn = tsdn_fetch(); 128 | 129 | /* Verify allocations. */ 130 | for (i = 0; i < nptrs; i++) { 131 | assert_zu_gt(ivsalloc(tsdn, ptrs[i], false), 0, 132 | "Allocation should have queryable size"); 133 | } 134 | 135 | /* Reset. */ 136 | miblen = sizeof(mib)/sizeof(size_t); 137 | assert_d_eq(mallctlnametomib("arena.0.reset", mib, &miblen), 0, 138 | "Unexpected mallctlnametomib() failure"); 139 | mib[1] = (size_t)arena_ind; 140 | assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0, 141 | "Unexpected mallctlbymib() failure"); 142 | 143 | /* Verify allocations no longer exist. */ 144 | for (i = 0; i < nptrs; i++) { 145 | assert_zu_eq(ivsalloc(tsdn, ptrs[i], false), 0, 146 | "Allocation should no longer exist"); 147 | } 148 | 149 | free(ptrs); 150 | } 151 | TEST_END 152 | 153 | int 154 | main(void) 155 | { 156 | 157 | return (test( 158 | test_arena_reset)); 159 | } 160 | -------------------------------------------------------------------------------- /test/unit/prof_active.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #ifdef JEMALLOC_PROF 4 | const char *malloc_conf = 5 | "prof:true,prof_thread_active_init:false,lg_prof_sample:0"; 6 | #endif 7 | 8 | static void 9 | mallctl_bool_get(const char *name, bool expected, const char *func, int line) 10 | { 11 | bool old; 12 | size_t sz; 13 | 14 | sz = sizeof(old); 15 | assert_d_eq(mallctl(name, &old, &sz, NULL, 0), 0, 16 | "%s():%d: Unexpected mallctl failure reading %s", func, line, name); 17 | assert_b_eq(old, expected, "%s():%d: Unexpected %s value", func, line, 18 | name); 19 | } 20 | 21 | static void 22 | mallctl_bool_set(const char *name, bool old_expected, bool val_new, 23 | const char *func, int line) 24 | { 25 | bool old; 26 | size_t sz; 27 | 28 | sz = sizeof(old); 29 | assert_d_eq(mallctl(name, &old, &sz, &val_new, sizeof(val_new)), 0, 30 | "%s():%d: Unexpected mallctl failure reading/writing %s", func, 31 | line, name); 32 | assert_b_eq(old, old_expected, "%s():%d: Unexpected %s value", func, 33 | line, name); 34 | } 35 | 36 | static void 37 | mallctl_prof_active_get_impl(bool prof_active_old_expected, const char *func, 38 | int line) 39 | { 40 | 41 | mallctl_bool_get("prof.active", prof_active_old_expected, func, line); 42 | } 43 | #define mallctl_prof_active_get(a) \ 44 | mallctl_prof_active_get_impl(a, __func__, __LINE__) 45 | 46 | static void 47 | mallctl_prof_active_set_impl(bool prof_active_old_expected, 48 | bool prof_active_new, const char *func, int line) 49 | { 50 | 51 | mallctl_bool_set("prof.active", prof_active_old_expected, 52 | prof_active_new, func, line); 53 | } 54 | #define mallctl_prof_active_set(a, b) \ 55 | mallctl_prof_active_set_impl(a, b, __func__, __LINE__) 56 | 57 | static void 58 | mallctl_thread_prof_active_get_impl(bool thread_prof_active_old_expected, 59 | const char *func, int line) 60 | { 61 | 62 | mallctl_bool_get("thread.prof.active", thread_prof_active_old_expected, 63 | func, line); 64 | } 65 | #define mallctl_thread_prof_active_get(a) \ 66 | mallctl_thread_prof_active_get_impl(a, __func__, __LINE__) 67 | 68 | static void 69 | mallctl_thread_prof_active_set_impl(bool thread_prof_active_old_expected, 70 | bool thread_prof_active_new, const char *func, int line) 71 | { 72 | 73 | mallctl_bool_set("thread.prof.active", thread_prof_active_old_expected, 74 | thread_prof_active_new, func, line); 75 | } 76 | #define mallctl_thread_prof_active_set(a, b) \ 77 | mallctl_thread_prof_active_set_impl(a, b, __func__, __LINE__) 78 | 79 | static void 80 | prof_sampling_probe_impl(bool expect_sample, const char *func, int line) 81 | { 82 | void *p; 83 | size_t expected_backtraces = expect_sample ? 1 : 0; 84 | 85 | assert_zu_eq(prof_bt_count(), 0, "%s():%d: Expected 0 backtraces", func, 86 | line); 87 | p = mallocx(1, 0); 88 | assert_ptr_not_null(p, "Unexpected mallocx() failure"); 89 | assert_zu_eq(prof_bt_count(), expected_backtraces, 90 | "%s():%d: Unexpected backtrace count", func, line); 91 | dallocx(p, 0); 92 | } 93 | #define prof_sampling_probe(a) \ 94 | prof_sampling_probe_impl(a, __func__, __LINE__) 95 | 96 | TEST_BEGIN(test_prof_active) 97 | { 98 | 99 | test_skip_if(!config_prof); 100 | 101 | mallctl_prof_active_get(true); 102 | mallctl_thread_prof_active_get(false); 103 | 104 | mallctl_prof_active_set(true, true); 105 | mallctl_thread_prof_active_set(false, false); 106 | /* prof.active, !thread.prof.active. */ 107 | prof_sampling_probe(false); 108 | 109 | mallctl_prof_active_set(true, false); 110 | mallctl_thread_prof_active_set(false, false); 111 | /* !prof.active, !thread.prof.active. */ 112 | prof_sampling_probe(false); 113 | 114 | mallctl_prof_active_set(false, false); 115 | mallctl_thread_prof_active_set(false, true); 116 | /* !prof.active, thread.prof.active. */ 117 | prof_sampling_probe(false); 118 | 119 | mallctl_prof_active_set(false, true); 120 | mallctl_thread_prof_active_set(true, true); 121 | /* prof.active, thread.prof.active. */ 122 | prof_sampling_probe(true); 123 | 124 | /* Restore settings. */ 125 | mallctl_prof_active_set(true, true); 126 | mallctl_thread_prof_active_set(true, false); 127 | } 128 | TEST_END 129 | 130 | int 131 | main(void) 132 | { 133 | 134 | return (test( 135 | test_prof_active)); 136 | } 137 | -------------------------------------------------------------------------------- /src/nstime.c: -------------------------------------------------------------------------------- 1 | #include "jemalloc/internal/jemalloc_internal.h" 2 | 3 | #define BILLION UINT64_C(1000000000) 4 | 5 | void 6 | nstime_init(nstime_t *time, uint64_t ns) 7 | { 8 | 9 | time->ns = ns; 10 | } 11 | 12 | void 13 | nstime_init2(nstime_t *time, uint64_t sec, uint64_t nsec) 14 | { 15 | 16 | time->ns = sec * BILLION + nsec; 17 | } 18 | 19 | uint64_t 20 | nstime_ns(const nstime_t *time) 21 | { 22 | 23 | return (time->ns); 24 | } 25 | 26 | uint64_t 27 | nstime_sec(const nstime_t *time) 28 | { 29 | 30 | return (time->ns / BILLION); 31 | } 32 | 33 | uint64_t 34 | nstime_nsec(const nstime_t *time) 35 | { 36 | 37 | return (time->ns % BILLION); 38 | } 39 | 40 | void 41 | nstime_copy(nstime_t *time, const nstime_t *source) 42 | { 43 | 44 | *time = *source; 45 | } 46 | 47 | int 48 | nstime_compare(const nstime_t *a, const nstime_t *b) 49 | { 50 | 51 | return ((a->ns > b->ns) - (a->ns < b->ns)); 52 | } 53 | 54 | void 55 | nstime_add(nstime_t *time, const nstime_t *addend) 56 | { 57 | 58 | assert(UINT64_MAX - time->ns >= addend->ns); 59 | 60 | time->ns += addend->ns; 61 | } 62 | 63 | void 64 | nstime_subtract(nstime_t *time, const nstime_t *subtrahend) 65 | { 66 | 67 | assert(nstime_compare(time, subtrahend) >= 0); 68 | 69 | time->ns -= subtrahend->ns; 70 | } 71 | 72 | void 73 | nstime_imultiply(nstime_t *time, uint64_t multiplier) 74 | { 75 | 76 | assert((((time->ns | multiplier) & (UINT64_MAX << (sizeof(uint64_t) << 77 | 2))) == 0) || ((time->ns * multiplier) / multiplier == time->ns)); 78 | 79 | time->ns *= multiplier; 80 | } 81 | 82 | void 83 | nstime_idivide(nstime_t *time, uint64_t divisor) 84 | { 85 | 86 | assert(divisor != 0); 87 | 88 | time->ns /= divisor; 89 | } 90 | 91 | uint64_t 92 | nstime_divide(const nstime_t *time, const nstime_t *divisor) 93 | { 94 | 95 | assert(divisor->ns != 0); 96 | 97 | return (time->ns / divisor->ns); 98 | } 99 | 100 | #ifdef _WIN32 101 | # define NSTIME_MONOTONIC true 102 | static void 103 | nstime_get(nstime_t *time) 104 | { 105 | FILETIME ft; 106 | uint64_t ticks_100ns; 107 | 108 | GetSystemTimeAsFileTime(&ft); 109 | ticks_100ns = (((uint64_t)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; 110 | 111 | nstime_init(time, ticks_100ns * 100); 112 | } 113 | #elif JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE 114 | # define NSTIME_MONOTONIC true 115 | static void 116 | nstime_get(nstime_t *time) 117 | { 118 | struct timespec ts; 119 | 120 | clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); 121 | nstime_init2(time, ts.tv_sec, ts.tv_nsec); 122 | } 123 | #elif JEMALLOC_HAVE_CLOCK_MONOTONIC 124 | # define NSTIME_MONOTONIC true 125 | static void 126 | nstime_get(nstime_t *time) 127 | { 128 | struct timespec ts; 129 | 130 | clock_gettime(CLOCK_MONOTONIC, &ts); 131 | nstime_init2(time, ts.tv_sec, ts.tv_nsec); 132 | } 133 | #elif JEMALLOC_HAVE_MACH_ABSOLUTE_TIME 134 | # define NSTIME_MONOTONIC true 135 | static void 136 | nstime_get(nstime_t *time) 137 | { 138 | 139 | nstime_init(time, mach_absolute_time()); 140 | } 141 | #else 142 | # define NSTIME_MONOTONIC false 143 | static void 144 | nstime_get(nstime_t *time) 145 | { 146 | struct timeval tv; 147 | 148 | gettimeofday(&tv, NULL); 149 | nstime_init2(time, tv.tv_sec, tv.tv_usec * 1000); 150 | } 151 | #endif 152 | 153 | #ifdef JEMALLOC_JET 154 | #undef nstime_monotonic 155 | #define nstime_monotonic JEMALLOC_N(n_nstime_monotonic) 156 | #endif 157 | bool 158 | nstime_monotonic(void) 159 | { 160 | 161 | return (NSTIME_MONOTONIC); 162 | #undef NSTIME_MONOTONIC 163 | } 164 | #ifdef JEMALLOC_JET 165 | #undef nstime_monotonic 166 | #define nstime_monotonic JEMALLOC_N(nstime_monotonic) 167 | nstime_monotonic_t *nstime_monotonic = JEMALLOC_N(n_nstime_monotonic); 168 | #endif 169 | 170 | #ifdef JEMALLOC_JET 171 | #undef nstime_update 172 | #define nstime_update JEMALLOC_N(n_nstime_update) 173 | #endif 174 | bool 175 | nstime_update(nstime_t *time) 176 | { 177 | nstime_t old_time; 178 | 179 | nstime_copy(&old_time, time); 180 | nstime_get(time); 181 | 182 | /* Handle non-monotonic clocks. */ 183 | if (unlikely(nstime_compare(&old_time, time) > 0)) { 184 | nstime_copy(time, &old_time); 185 | return (true); 186 | } 187 | 188 | return (false); 189 | } 190 | #ifdef JEMALLOC_JET 191 | #undef nstime_update 192 | #define nstime_update JEMALLOC_N(nstime_update) 193 | nstime_update_t *nstime_update = JEMALLOC_N(n_nstime_update); 194 | #endif 195 | --------------------------------------------------------------------------------