├── .gitignore ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.in ├── README ├── autogen.sh ├── bin ├── jemalloc.sh.in └── pprof ├── config.guess ├── config.stamp.in ├── config.sub ├── configure.ac ├── coverage.sh ├── doc ├── html.xsl.in ├── jemalloc.xml.in ├── manpages.xsl.in └── stylesheet.xsl ├── include ├── jemalloc │ ├── internal │ │ ├── arena.h │ │ ├── atomic.h │ │ ├── base.h │ │ ├── bitmap.h │ │ ├── chunk.h │ │ ├── chunk_dss.h │ │ ├── chunk_mmap.h │ │ ├── ckh.h │ │ ├── ctl.h │ │ ├── extent.h │ │ ├── hash.h │ │ ├── huge.h │ │ ├── jemalloc_internal.h.in │ │ ├── jemalloc_internal_defs.h.in │ │ ├── jemalloc_internal_macros.h │ │ ├── mb.h │ │ ├── mutex.h │ │ ├── private_namespace.sh │ │ ├── private_symbols.txt │ │ ├── private_unnamespace.sh │ │ ├── prng.h │ │ ├── prof.h │ │ ├── public_namespace.sh │ │ ├── public_unnamespace.sh │ │ ├── ql.h │ │ ├── qr.h │ │ ├── quarantine.h │ │ ├── rb.h │ │ ├── rtree.h │ │ ├── size_classes.sh │ │ ├── stats.h │ │ ├── tcache.h │ │ ├── tsd.h │ │ └── util.h │ ├── jemalloc.sh │ ├── jemalloc_defs.h.in │ ├── jemalloc_macros.h.in │ ├── jemalloc_mangle.sh │ ├── jemalloc_protos.h.in │ └── jemalloc_rename.sh └── msvc_compat │ ├── inttypes.h │ ├── stdbool.h │ ├── stdint.h │ └── strings.h ├── install-sh ├── jemalloc-3.5.1+mk3.spec ├── src ├── arena.c ├── atomic.c ├── base.c ├── bitmap.c ├── chunk.c ├── chunk_dss.c ├── chunk_mmap.c ├── ckh.c ├── ctl.c ├── extent.c ├── hash.c ├── huge.c ├── jemalloc.c ├── mb.c ├── mutex.c ├── prof.c ├── quarantine.c ├── rtree.c ├── stats.c ├── tcache.c ├── tsd.c ├── util.c └── zone.c └── test ├── include └── test │ ├── SFMT-alti.h │ ├── SFMT-params.h │ ├── SFMT-params11213.h │ ├── SFMT-params1279.h │ ├── SFMT-params132049.h │ ├── SFMT-params19937.h │ ├── SFMT-params216091.h │ ├── SFMT-params2281.h │ ├── SFMT-params4253.h │ ├── SFMT-params44497.h │ ├── SFMT-params607.h │ ├── SFMT-params86243.h │ ├── SFMT-sse2.h │ ├── SFMT.h │ ├── jemalloc_test.h.in │ ├── jemalloc_test_defs.h.in │ ├── math.h │ ├── mq.h │ ├── mtx.h │ ├── test.h │ ├── thd.h │ └── timer.h ├── integration ├── ALLOCM_ARENA.c ├── aligned_alloc.c ├── allocated.c ├── allocm.c ├── mallocx.c ├── mremap.c ├── posix_memalign.c ├── rallocm.c ├── rallocx.c ├── thread_arena.c ├── thread_tcache_enabled.c └── xallocx.c ├── src ├── SFMT.c ├── math.c ├── mtx.c ├── test.c ├── thd.c └── timer.c ├── stress └── microbench.c ├── test.sh.in └── unit ├── SFMT.c ├── bitmap.c ├── ckh.c ├── hash.c ├── junk.c ├── mallctl.c ├── math.c ├── mq.c ├── mtx.c ├── prof_accum.c ├── prof_accum.h ├── prof_accum_a.c ├── prof_accum_b.c ├── prof_gdump.c ├── prof_idump.c ├── ql.c ├── qr.c ├── quarantine.c ├── rb.c ├── rtree.c ├── stats.c ├── tsd.c ├── util.c └── zero.c /.gitignore: -------------------------------------------------------------------------------- 1 | /*.gcov.* 2 | 3 | /autom4te.cache/ 4 | 5 | /bin/jemalloc.sh 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 | /lib/ 19 | 20 | /Makefile 21 | 22 | /include/jemalloc/internal/jemalloc_internal.h 23 | /include/jemalloc/internal/jemalloc_internal_defs.h 24 | /include/jemalloc/internal/private_namespace.h 25 | /include/jemalloc/internal/private_unnamespace.h 26 | /include/jemalloc/internal/public_namespace.h 27 | /include/jemalloc/internal/public_symbols.txt 28 | /include/jemalloc/internal/public_unnamespace.h 29 | /include/jemalloc/internal/size_classes.h 30 | /include/jemalloc/jemalloc.h 31 | /include/jemalloc/jemalloc_defs.h 32 | /include/jemalloc/jemalloc_macros.h 33 | /include/jemalloc/jemalloc_mangle.h 34 | /include/jemalloc/jemalloc_mangle_jet.h 35 | /include/jemalloc/jemalloc_protos.h 36 | /include/jemalloc/jemalloc_protos_jet.h 37 | /include/jemalloc/jemalloc_rename.h 38 | 39 | /src/*.[od] 40 | /src/*.gcda 41 | /src/*.gcno 42 | 43 | /test/test.sh 44 | test/include/test/jemalloc_test.h 45 | test/include/test/jemalloc_test_defs.h 46 | 47 | /test/integration/[A-Za-z]* 48 | !/test/integration/[A-Za-z]*.* 49 | /test/integration/*.[od] 50 | /test/integration/*.gcda 51 | /test/integration/*.gcno 52 | /test/integration/*.out 53 | 54 | /test/src/*.[od] 55 | /test/src/*.gcda 56 | /test/src/*.gcno 57 | 58 | /test/stress/[A-Za-z]* 59 | !/test/stress/[A-Za-z]*.* 60 | /test/stress/*.[od] 61 | /test/stress/*.gcda 62 | /test/stress/*.gcno 63 | /test/stress/*.out 64 | 65 | /test/unit/[A-Za-z]* 66 | !/test/unit/[A-Za-z]*.* 67 | /test/unit/*.[od] 68 | /test/unit/*.gcda 69 | /test/unit/*.gcno 70 | /test/unit/*.out 71 | 72 | /VERSION 73 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Unless otherwise specified, files in the jemalloc source distribution are 2 | subject to the following license: 3 | -------------------------------------------------------------------------------- 4 | Copyright (C) 2002-2014 Jason Evans . 5 | All rights reserved. 6 | Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved. 7 | Copyright (C) 2009-2014 Facebook, Inc. All rights reserved. 8 | Copyright (C) 2014, 2015 Intel Corporation All Rights Reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 1. Redistributions of source code must retain the above copyright notice(s), 13 | this list of conditions and the following disclaimer. 14 | 2. Redistributions in binary form must reproduce the above copyright notice(s), 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS 19 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 21 | EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- 29 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | THIS SOFTWARE IS PROVIDED AS A DEVELOPMENT SNAPSHOT TO AID 2 | COLLABORATION AND WAS NOT ISSUED AS A RELEASED PRODUCT BY INTEL. 3 | DOCUMENTATION AND TEST CODE COVERAGE ARE INCOMPLETE. 4 | 5 | jemalloc is a general purpose malloc(3) implementation that emphasizes 6 | fragmentation avoidance and scalable concurrency support. jemalloc 7 | first came into use as the FreeBSD libc allocator in 2005, and since 8 | then it has found its way into numerous applications that rely on its 9 | predictable behavior. In 2010 jemalloc development efforts broadened 10 | to include developer support features such as heap profiling, Valgrind 11 | integration, and extensive monitoring/tuning hooks. Modern jemalloc 12 | releases continue to be integrated back into FreeBSD, and therefore 13 | versatility remains critical. Ongoing development efforts trend 14 | toward making jemalloc among the best allocators for a broad range of 15 | demanding applications, and eliminating/mitigating weaknesses that 16 | have practical repercussions for real world applications. 17 | 18 | This version of jemalloc has been modified to enable the memkind 19 | library. This modification gives the user the ability to create 20 | arenas which are tagged with a partition index. All allocations done 21 | within a tagged area are kept separate in the heap so that freed 22 | memory segments with different partition indices are not coalesced. 23 | The tagging of arenas and management of their allocations is done by 24 | the memkind library. The tag controls the flags passed to mmap() and 25 | provides a wrapper implementation of mbind(). In this way page size 26 | and NUMA features are enabled. 27 | 28 | 29 | The COPYING file contains copyright and licensing information. 30 | 31 | The INSTALL file contains information on how to configure, build, and install 32 | jemalloc. 33 | 34 | The ChangeLog file contains a brief summary of changes for each release. 35 | 36 | URLs: http://www.canonware.com/jemalloc/ 37 | https://github.com/memkind/jemalloc/ 38 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /config.stamp.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/memkind/jemalloc/477d9c95a0d3931c8fb8c3bd808eeea12943321c/config.stamp.in -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /doc/html.xsl.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /doc/manpages.xsl.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /doc/stylesheet.xsl: -------------------------------------------------------------------------------- 1 | 2 | ansi 3 | 4 | 5 | "" 6 | 7 | 8 | -------------------------------------------------------------------------------- /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(size_t size); 13 | void *base_calloc(size_t number, size_t size); 14 | extent_node_t *base_node_alloc(void); 15 | void base_node_dealloc(extent_node_t *node); 16 | bool base_boot(void); 17 | void base_prefork(void); 18 | void base_postfork_parent(void); 19 | void base_postfork_child(void); 20 | 21 | #endif /* JEMALLOC_H_EXTERNS */ 22 | /******************************************************************************/ 23 | #ifdef JEMALLOC_H_INLINES 24 | 25 | #endif /* JEMALLOC_H_INLINES */ 26 | /******************************************************************************/ 27 | -------------------------------------------------------------------------------- /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 22 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 | #endif /* JEMALLOC_H_TYPES */ 23 | /******************************************************************************/ 24 | #ifdef JEMALLOC_H_STRUCTS 25 | 26 | #endif /* JEMALLOC_H_STRUCTS */ 27 | /******************************************************************************/ 28 | #ifdef JEMALLOC_H_EXTERNS 29 | 30 | extern size_t opt_lg_chunk; 31 | extern const char *opt_dss; 32 | 33 | /* Protects stats_chunks; currently not used for any other purpose. */ 34 | extern malloc_mutex_t chunks_mtx; 35 | /* Chunk statistics. */ 36 | extern chunk_stats_t stats_chunks; 37 | 38 | extern rtree_t *chunks_rtree; 39 | 40 | extern size_t chunksize; 41 | extern size_t chunksize_mask; /* (chunksize - 1). */ 42 | extern size_t chunk_npages; 43 | extern size_t map_bias; /* Number of arena chunk header pages. */ 44 | extern size_t arena_maxclass; /* Max size class for arenas. */ 45 | 46 | void *chunk_alloc(size_t size, size_t alignment, bool base, bool *zero, 47 | dss_prec_t dss_prec 48 | #ifdef JEMALLOC_ENABLE_MEMKIND 49 | , unsigned partition 50 | #endif 51 | ); 52 | void chunk_unmap(void *chunk, size_t size 53 | #ifdef JEMALLOC_ENABLE_MEMKIND 54 | , unsigned partition 55 | #endif 56 | ); 57 | void chunk_dealloc(void *chunk, size_t size, bool unmap 58 | #ifdef JEMALLOC_ENABLE_MEMKIND 59 | , unsigned partition 60 | #endif 61 | ); 62 | bool chunk_boot(void); 63 | void chunk_prefork(void); 64 | void chunk_postfork_parent(void); 65 | void chunk_postfork_child(void); 66 | 67 | #endif /* JEMALLOC_H_EXTERNS */ 68 | /******************************************************************************/ 69 | #ifdef JEMALLOC_H_INLINES 70 | 71 | #endif /* JEMALLOC_H_INLINES */ 72 | /******************************************************************************/ 73 | 74 | #include "jemalloc/internal/chunk_dss.h" 75 | #include "jemalloc/internal/chunk_mmap.h" 76 | -------------------------------------------------------------------------------- /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(size_t size, size_t alignment, bool *zero); 27 | bool chunk_in_dss(void *chunk); 28 | bool chunk_dss_boot(void); 29 | void chunk_dss_prefork(void); 30 | void chunk_dss_postfork_parent(void); 31 | void chunk_dss_postfork_child(void); 32 | 33 | #endif /* JEMALLOC_H_EXTERNS */ 34 | /******************************************************************************/ 35 | #ifdef JEMALLOC_H_INLINES 36 | 37 | #endif /* JEMALLOC_H_INLINES */ 38 | /******************************************************************************/ 39 | -------------------------------------------------------------------------------- /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 | bool pages_purge(void *addr, size_t length 13 | #ifdef JEMALLOC_ENABLE_MEMKIND 14 | , bool file_mapped 15 | #endif 16 | ); 17 | 18 | void *chunk_alloc_mmap(size_t size, size_t alignment, bool *zero 19 | #ifdef JEMALLOC_ENABLE_MEMKIND 20 | , unsigned partition 21 | #endif 22 | ); 23 | bool chunk_dealloc_mmap(void *chunk, size_t size); 24 | 25 | #endif /* JEMALLOC_H_EXTERNS */ 26 | /******************************************************************************/ 27 | #ifdef JEMALLOC_H_INLINES 28 | 29 | #endif /* JEMALLOC_H_INLINES */ 30 | /******************************************************************************/ 31 | -------------------------------------------------------------------------------- /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 | #define CKH_A 1103515241 44 | #define CKH_C 12347 45 | uint32_t prng_state; 46 | 47 | /* Total number of items. */ 48 | size_t count; 49 | 50 | /* 51 | * Minimum and current number of hash table buckets. There are 52 | * 2^LG_CKH_BUCKET_CELLS cells per bucket. 53 | */ 54 | unsigned lg_minbuckets; 55 | unsigned lg_curbuckets; 56 | 57 | /* Hash and comparison functions. */ 58 | ckh_hash_t *hash; 59 | ckh_keycomp_t *keycomp; 60 | 61 | /* Hash table with 2^lg_curbuckets buckets. */ 62 | ckhc_t *tab; 63 | }; 64 | 65 | #endif /* JEMALLOC_H_STRUCTS */ 66 | /******************************************************************************/ 67 | #ifdef JEMALLOC_H_EXTERNS 68 | 69 | bool ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, 70 | ckh_keycomp_t *keycomp); 71 | void ckh_delete(ckh_t *ckh); 72 | size_t ckh_count(ckh_t *ckh); 73 | bool ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data); 74 | bool ckh_insert(ckh_t *ckh, const void *key, const void *data); 75 | bool ckh_remove(ckh_t *ckh, const void *searchkey, void **key, 76 | void **data); 77 | bool ckh_search(ckh_t *ckh, const void *seachkey, void **key, void **data); 78 | void ckh_string_hash(const void *key, size_t r_hash[2]); 79 | bool ckh_string_keycomp(const void *k1, const void *k2); 80 | void ckh_pointer_hash(const void *key, size_t r_hash[2]); 81 | bool ckh_pointer_keycomp(const void *k1, const void *k2); 82 | 83 | #endif /* JEMALLOC_H_EXTERNS */ 84 | /******************************************************************************/ 85 | #ifdef JEMALLOC_H_INLINES 86 | 87 | #endif /* JEMALLOC_H_INLINES */ 88 | /******************************************************************************/ 89 | -------------------------------------------------------------------------------- /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)(const size_t *, size_t, void *, size_t *, 25 | void *, size_t); 26 | }; 27 | 28 | struct ctl_indexed_node_s { 29 | struct ctl_node_s node; 30 | const ctl_named_node_t *(*index)(const size_t *, size_t, size_t); 31 | }; 32 | 33 | struct ctl_arena_stats_s { 34 | bool initialized; 35 | unsigned nthreads; 36 | const char *dss; 37 | size_t pactive; 38 | size_t pdirty; 39 | arena_stats_t astats; 40 | 41 | /* Aggregate stats for small size classes, based on bin stats. */ 42 | size_t allocated_small; 43 | uint64_t nmalloc_small; 44 | uint64_t ndalloc_small; 45 | uint64_t nrequests_small; 46 | 47 | malloc_bin_stats_t bstats[NBINS]; 48 | malloc_large_stats_t *lstats; /* nlclasses elements. */ 49 | }; 50 | 51 | struct ctl_stats_s { 52 | size_t allocated; 53 | size_t active; 54 | size_t mapped; 55 | struct { 56 | size_t current; /* stats_chunks.curchunks */ 57 | uint64_t total; /* stats_chunks.nchunks */ 58 | size_t high; /* stats_chunks.highchunks */ 59 | } chunks; 60 | struct { 61 | size_t allocated; /* huge_allocated */ 62 | uint64_t nmalloc; /* huge_nmalloc */ 63 | uint64_t ndalloc; /* huge_ndalloc */ 64 | } huge; 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(const char *name, void *oldp, size_t *oldlenp, void *newp, 74 | size_t newlen); 75 | int ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp); 76 | 77 | int ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, 78 | void *newp, size_t newlen); 79 | bool ctl_boot(void); 80 | void ctl_prefork(void); 81 | void ctl_postfork_parent(void); 82 | void ctl_postfork_child(void); 83 | 84 | #define xmallctl(name, oldp, oldlenp, newp, newlen) do { \ 85 | if (je_mallctl(name, oldp, oldlenp, newp, newlen) \ 86 | != 0) { \ 87 | malloc_printf( \ 88 | ": Failure in xmallctl(\"%s\", ...)\n", \ 89 | name); \ 90 | abort(); \ 91 | } \ 92 | } while (0) 93 | 94 | #define xmallctlnametomib(name, mibp, miblenp) do { \ 95 | if (je_mallctlnametomib(name, mibp, miblenp) != 0) { \ 96 | malloc_printf(": Failure in " \ 97 | "xmallctlnametomib(\"%s\", ...)\n", name); \ 98 | abort(); \ 99 | } \ 100 | } while (0) 101 | 102 | #define xmallctlbymib(mib, miblen, oldp, oldlenp, newp, newlen) do { \ 103 | if (je_mallctlbymib(mib, miblen, oldp, oldlenp, newp, \ 104 | newlen) != 0) { \ 105 | malloc_write( \ 106 | ": Failure in xmallctlbymib()\n"); \ 107 | abort(); \ 108 | } \ 109 | } while (0) 110 | 111 | #endif /* JEMALLOC_H_EXTERNS */ 112 | /******************************************************************************/ 113 | #ifdef JEMALLOC_H_INLINES 114 | 115 | #endif /* JEMALLOC_H_INLINES */ 116 | /******************************************************************************/ 117 | 118 | -------------------------------------------------------------------------------- /include/jemalloc/internal/extent.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | typedef struct extent_node_s extent_node_t; 5 | 6 | #endif /* JEMALLOC_H_TYPES */ 7 | /******************************************************************************/ 8 | #ifdef JEMALLOC_H_STRUCTS 9 | 10 | /* Tree of extents. */ 11 | struct extent_node_s { 12 | /* Linkage for the size/address-ordered tree. */ 13 | rb_node(extent_node_t) link_szad; 14 | 15 | /* Linkage for the address-ordered tree. */ 16 | rb_node(extent_node_t) link_ad; 17 | 18 | /* Profile counters, used for huge objects. */ 19 | prof_ctx_t *prof_ctx; 20 | 21 | /* Pointer to the extent that this tree node is responsible for. */ 22 | void *addr; 23 | 24 | /* Total region size. */ 25 | size_t size; 26 | 27 | /* True if zero-filled; used by chunk recycling code. */ 28 | bool zeroed; 29 | 30 | /* Numa kind associated with the extent. */ 31 | #ifdef JEMALLOC_ENABLE_MEMKIND 32 | unsigned partition; 33 | #endif 34 | }; 35 | typedef rb_tree(extent_node_t) extent_tree_t; 36 | 37 | #endif /* JEMALLOC_H_STRUCTS */ 38 | /******************************************************************************/ 39 | #ifdef JEMALLOC_H_EXTERNS 40 | 41 | rb_proto(, extent_tree_szad_, extent_tree_t, extent_node_t) 42 | 43 | rb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t) 44 | 45 | #endif /* JEMALLOC_H_EXTERNS */ 46 | /******************************************************************************/ 47 | #ifdef JEMALLOC_H_INLINES 48 | 49 | #endif /* JEMALLOC_H_INLINES */ 50 | /******************************************************************************/ 51 | 52 | -------------------------------------------------------------------------------- /include/jemalloc/internal/huge.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 | /* Huge allocation statistics. */ 13 | extern uint64_t huge_nmalloc; 14 | extern uint64_t huge_ndalloc; 15 | extern size_t huge_allocated; 16 | 17 | /* Protects chunk-related data structures. */ 18 | extern malloc_mutex_t huge_mtx; 19 | 20 | void *huge_malloc(size_t size, bool zero 21 | #ifdef JEMALLOC_ENABLE_MEMKIND 22 | , unsigned partition 23 | #endif 24 | ); 25 | void *huge_palloc(size_t size, size_t alignment, bool zero 26 | #ifdef JEMALLOC_ENABLE_MEMKIND 27 | , unsigned partition 28 | #endif 29 | ); 30 | bool huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, 31 | size_t extra); 32 | void *huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, 33 | size_t alignment, bool zero, bool try_tcache_dalloc 34 | #ifdef JEMALLOC_ENABLE_MEMKIND 35 | , unsigned partition 36 | #endif 37 | ); 38 | #ifdef JEMALLOC_JET 39 | typedef void (huge_dalloc_junk_t)(void *, size_t); 40 | extern huge_dalloc_junk_t *huge_dalloc_junk; 41 | #endif 42 | void huge_dalloc(void *ptr, bool unmap); 43 | size_t huge_salloc(const void *ptr 44 | #ifdef JEMALLOC_ENABLE_MEMKIND 45 | , unsigned partition 46 | #endif 47 | ); 48 | prof_ctx_t *huge_prof_ctx_get(const void *ptr); 49 | void huge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx); 50 | bool huge_boot(void); 51 | void huge_prefork(void); 52 | void huge_postfork_parent(void); 53 | void huge_postfork_child(void); 54 | 55 | #endif /* JEMALLOC_H_EXTERNS */ 56 | /******************************************************************************/ 57 | #ifdef JEMALLOC_H_INLINES 58 | 59 | #endif /* JEMALLOC_H_INLINES */ 60 | /******************************************************************************/ 61 | -------------------------------------------------------------------------------- /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 QU(q) ((uint64_t)q) 43 | #define QI(q) ((int64_t)q) 44 | 45 | #ifndef __DECONST 46 | # define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) 47 | #endif 48 | 49 | #ifndef JEMALLOC_HAS_RESTRICT 50 | # define restrict 51 | #endif 52 | -------------------------------------------------------------------------------- /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); 108 | malloc_mutex_lock(&mtx); 109 | malloc_mutex_unlock(&mtx); 110 | } 111 | #endif 112 | #endif 113 | 114 | #endif /* JEMALLOC_H_INLINES */ 115 | /******************************************************************************/ 116 | -------------------------------------------------------------------------------- /include/jemalloc/internal/mutex.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | typedef struct malloc_mutex_s malloc_mutex_t; 5 | 6 | #ifdef _WIN32 7 | # define MALLOC_MUTEX_INITIALIZER 8 | #elif (defined(JEMALLOC_OSSPIN)) 9 | # define MALLOC_MUTEX_INITIALIZER {0} 10 | #elif (defined(JEMALLOC_MUTEX_INIT_CB)) 11 | # define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL} 12 | #else 13 | # if (defined(PTHREAD_MUTEX_ADAPTIVE_NP) && \ 14 | defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)) 15 | # define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_ADAPTIVE_NP 16 | # define MALLOC_MUTEX_INITIALIZER {PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP} 17 | # else 18 | # define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT 19 | # define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER} 20 | # endif 21 | #endif 22 | 23 | #endif /* JEMALLOC_H_TYPES */ 24 | /******************************************************************************/ 25 | #ifdef JEMALLOC_H_STRUCTS 26 | 27 | struct malloc_mutex_s { 28 | #ifdef _WIN32 29 | CRITICAL_SECTION lock; 30 | #elif (defined(JEMALLOC_OSSPIN)) 31 | OSSpinLock lock; 32 | #elif (defined(JEMALLOC_MUTEX_INIT_CB)) 33 | pthread_mutex_t lock; 34 | malloc_mutex_t *postponed_next; 35 | #else 36 | pthread_mutex_t lock; 37 | #endif 38 | }; 39 | 40 | #endif /* JEMALLOC_H_STRUCTS */ 41 | /******************************************************************************/ 42 | #ifdef JEMALLOC_H_EXTERNS 43 | 44 | #ifdef JEMALLOC_LAZY_LOCK 45 | extern bool isthreaded; 46 | #else 47 | # undef isthreaded /* Undo private_namespace.h definition. */ 48 | # define isthreaded true 49 | #endif 50 | 51 | bool malloc_mutex_init(malloc_mutex_t *mutex); 52 | void malloc_mutex_prefork(malloc_mutex_t *mutex); 53 | void malloc_mutex_postfork_parent(malloc_mutex_t *mutex); 54 | void malloc_mutex_postfork_child(malloc_mutex_t *mutex); 55 | bool mutex_boot(void); 56 | 57 | #endif /* JEMALLOC_H_EXTERNS */ 58 | /******************************************************************************/ 59 | #ifdef JEMALLOC_H_INLINES 60 | 61 | #ifndef JEMALLOC_ENABLE_INLINE 62 | void malloc_mutex_lock(malloc_mutex_t *mutex); 63 | void malloc_mutex_unlock(malloc_mutex_t *mutex); 64 | #endif 65 | 66 | #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_)) 67 | JEMALLOC_INLINE void 68 | malloc_mutex_lock(malloc_mutex_t *mutex) 69 | { 70 | 71 | if (isthreaded) { 72 | #ifdef _WIN32 73 | EnterCriticalSection(&mutex->lock); 74 | #elif (defined(JEMALLOC_OSSPIN)) 75 | OSSpinLockLock(&mutex->lock); 76 | #else 77 | pthread_mutex_lock(&mutex->lock); 78 | #endif 79 | } 80 | } 81 | 82 | JEMALLOC_INLINE void 83 | malloc_mutex_unlock(malloc_mutex_t *mutex) 84 | { 85 | 86 | if (isthreaded) { 87 | #ifdef _WIN32 88 | LeaveCriticalSection(&mutex->lock); 89 | #elif (defined(JEMALLOC_OSSPIN)) 90 | OSSpinLockUnlock(&mutex->lock); 91 | #else 92 | pthread_mutex_unlock(&mutex->lock); 93 | #endif 94 | } 95 | } 96 | #endif 97 | 98 | #endif /* JEMALLOC_H_INLINES */ 99 | /******************************************************************************/ 100 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /include/jemalloc/internal/private_unnamespace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for symbol in `cat $1` ; do 4 | echo "#undef ${symbol}" 5 | done 6 | -------------------------------------------------------------------------------- /include/jemalloc/internal/prng.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | /* 5 | * Simple linear congruential pseudo-random number generator: 6 | * 7 | * prng(y) = (a*x + c) % m 8 | * 9 | * where the following constants ensure maximal period: 10 | * 11 | * a == Odd number (relatively prime to 2^n), and (a-1) is a multiple of 4. 12 | * c == Odd number (relatively prime to 2^n). 13 | * m == 2^32 14 | * 15 | * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints. 16 | * 17 | * This choice of m has the disadvantage that the quality of the bits is 18 | * proportional to bit position. For example. the lowest bit has a cycle of 2, 19 | * the next has a cycle of 4, etc. For this reason, we prefer to use the upper 20 | * bits. 21 | * 22 | * Macro parameters: 23 | * uint32_t r : Result. 24 | * unsigned lg_range : (0..32], number of least significant bits to return. 25 | * uint32_t state : Seed value. 26 | * const uint32_t a, c : See above discussion. 27 | */ 28 | #define prng32(r, lg_range, state, a, c) do { \ 29 | assert(lg_range > 0); \ 30 | assert(lg_range <= 32); \ 31 | \ 32 | r = (state * (a)) + (c); \ 33 | state = r; \ 34 | r >>= (32 - lg_range); \ 35 | } while (false) 36 | 37 | /* Same as prng32(), but 64 bits of pseudo-randomness, using uint64_t. */ 38 | #define prng64(r, lg_range, state, a, c) do { \ 39 | assert(lg_range > 0); \ 40 | assert(lg_range <= 64); \ 41 | \ 42 | r = (state * (a)) + (c); \ 43 | state = r; \ 44 | r >>= (64 - lg_range); \ 45 | } while (false) 46 | 47 | #endif /* JEMALLOC_H_TYPES */ 48 | /******************************************************************************/ 49 | #ifdef JEMALLOC_H_STRUCTS 50 | 51 | #endif /* JEMALLOC_H_STRUCTS */ 52 | /******************************************************************************/ 53 | #ifdef JEMALLOC_H_EXTERNS 54 | 55 | #endif /* JEMALLOC_H_EXTERNS */ 56 | /******************************************************************************/ 57 | #ifdef JEMALLOC_H_INLINES 58 | 59 | #endif /* JEMALLOC_H_INLINES */ 60 | /******************************************************************************/ 61 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/jemalloc/internal/ql.h: -------------------------------------------------------------------------------- 1 | /* 2 | * List definitions. 3 | */ 4 | #define ql_head(a_type) \ 5 | struct { \ 6 | a_type *qlh_first; \ 7 | } 8 | 9 | #define ql_head_initializer(a_head) {NULL} 10 | 11 | #define ql_elm(a_type) qr(a_type) 12 | 13 | /* List functions. */ 14 | #define ql_new(a_head) do { \ 15 | (a_head)->qlh_first = NULL; \ 16 | } while (0) 17 | 18 | #define ql_elm_new(a_elm, a_field) qr_new((a_elm), a_field) 19 | 20 | #define ql_first(a_head) ((a_head)->qlh_first) 21 | 22 | #define ql_last(a_head, a_field) \ 23 | ((ql_first(a_head) != NULL) \ 24 | ? qr_prev(ql_first(a_head), a_field) : NULL) 25 | 26 | #define ql_next(a_head, a_elm, a_field) \ 27 | ((ql_last(a_head, a_field) != (a_elm)) \ 28 | ? qr_next((a_elm), a_field) : NULL) 29 | 30 | #define ql_prev(a_head, a_elm, a_field) \ 31 | ((ql_first(a_head) != (a_elm)) ? qr_prev((a_elm), a_field) \ 32 | : NULL) 33 | 34 | #define ql_before_insert(a_head, a_qlelm, a_elm, a_field) do { \ 35 | qr_before_insert((a_qlelm), (a_elm), a_field); \ 36 | if (ql_first(a_head) == (a_qlelm)) { \ 37 | ql_first(a_head) = (a_elm); \ 38 | } \ 39 | } while (0) 40 | 41 | #define ql_after_insert(a_qlelm, a_elm, a_field) \ 42 | qr_after_insert((a_qlelm), (a_elm), a_field) 43 | 44 | #define ql_head_insert(a_head, a_elm, a_field) do { \ 45 | if (ql_first(a_head) != NULL) { \ 46 | qr_before_insert(ql_first(a_head), (a_elm), a_field); \ 47 | } \ 48 | ql_first(a_head) = (a_elm); \ 49 | } while (0) 50 | 51 | #define ql_tail_insert(a_head, a_elm, a_field) do { \ 52 | if (ql_first(a_head) != NULL) { \ 53 | qr_before_insert(ql_first(a_head), (a_elm), a_field); \ 54 | } \ 55 | ql_first(a_head) = qr_next((a_elm), a_field); \ 56 | } while (0) 57 | 58 | #define ql_remove(a_head, a_elm, a_field) do { \ 59 | if (ql_first(a_head) == (a_elm)) { \ 60 | ql_first(a_head) = qr_next(ql_first(a_head), a_field); \ 61 | } \ 62 | if (ql_first(a_head) != (a_elm)) { \ 63 | qr_remove((a_elm), a_field); \ 64 | } else { \ 65 | ql_first(a_head) = NULL; \ 66 | } \ 67 | } while (0) 68 | 69 | #define ql_head_remove(a_head, a_type, a_field) do { \ 70 | a_type *t = ql_first(a_head); \ 71 | ql_remove((a_head), t, a_field); \ 72 | } while (0) 73 | 74 | #define ql_tail_remove(a_head, a_type, a_field) do { \ 75 | a_type *t = ql_last(a_head, a_field); \ 76 | ql_remove((a_head), t, a_field); \ 77 | } while (0) 78 | 79 | #define ql_foreach(a_var, a_head, a_field) \ 80 | qr_foreach((a_var), ql_first(a_head), a_field) 81 | 82 | #define ql_reverse_foreach(a_var, a_head, a_field) \ 83 | qr_reverse_foreach((a_var), ql_first(a_head), a_field) 84 | -------------------------------------------------------------------------------- /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 | /* qr_meld() and qr_split() are functionally equivalent, so there's no need to 44 | * have two copies of the code. */ 45 | #define qr_split(a_qr_a, a_qr_b, a_field) \ 46 | qr_meld((a_qr_a), (a_qr_b), a_field) 47 | 48 | #define qr_remove(a_qr, a_field) do { \ 49 | (a_qr)->a_field.qre_prev->a_field.qre_next \ 50 | = (a_qr)->a_field.qre_next; \ 51 | (a_qr)->a_field.qre_next->a_field.qre_prev \ 52 | = (a_qr)->a_field.qre_prev; \ 53 | (a_qr)->a_field.qre_next = (a_qr); \ 54 | (a_qr)->a_field.qre_prev = (a_qr); \ 55 | } while (0) 56 | 57 | #define qr_foreach(var, a_qr, a_field) \ 58 | for ((var) = (a_qr); \ 59 | (var) != NULL; \ 60 | (var) = (((var)->a_field.qre_next != (a_qr)) \ 61 | ? (var)->a_field.qre_next : NULL)) 62 | 63 | #define qr_reverse_foreach(var, a_qr, a_field) \ 64 | for ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL; \ 65 | (var) != NULL; \ 66 | (var) = (((var) != (a_qr)) \ 67 | ? (var)->a_field.qre_prev : NULL)) 68 | -------------------------------------------------------------------------------- /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 | quarantine_t *quarantine_init(size_t lg_maxobjs); 33 | void quarantine(void *ptr); 34 | void quarantine_cleanup(void *arg); 35 | bool quarantine_boot(void); 36 | 37 | #endif /* JEMALLOC_H_EXTERNS */ 38 | /******************************************************************************/ 39 | #ifdef JEMALLOC_H_INLINES 40 | 41 | #ifndef JEMALLOC_ENABLE_INLINE 42 | malloc_tsd_protos(JEMALLOC_ATTR(unused), quarantine, quarantine_t *) 43 | 44 | void quarantine_alloc_hook(void); 45 | #endif 46 | 47 | #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_QUARANTINE_C_)) 48 | malloc_tsd_externs(quarantine, quarantine_t *) 49 | malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, quarantine, quarantine_t *, NULL, 50 | quarantine_cleanup) 51 | 52 | JEMALLOC_ALWAYS_INLINE void 53 | quarantine_alloc_hook(void) 54 | { 55 | quarantine_t *quarantine; 56 | 57 | assert(config_fill && opt_quarantine); 58 | 59 | quarantine = *quarantine_tsd_get(); 60 | if (quarantine == NULL) 61 | quarantine_init(LG_MAXOBJS_INIT); 62 | } 63 | #endif 64 | 65 | #endif /* JEMALLOC_H_INLINES */ 66 | /******************************************************************************/ 67 | 68 | -------------------------------------------------------------------------------- /include/jemalloc/internal/size_classes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # The following limits are chosen such that they cover all supported platforms. 4 | 5 | # Range of quanta. 6 | lg_qmin=3 7 | lg_qmax=4 8 | 9 | # The range of tiny size classes is [2^lg_tmin..2^(lg_q-1)]. 10 | lg_tmin=3 11 | 12 | # Range of page sizes. 13 | lg_pmin=12 14 | lg_pmax=16 15 | 16 | pow2() { 17 | e=$1 18 | pow2_result=1 19 | while [ ${e} -gt 0 ] ; do 20 | pow2_result=$((${pow2_result} + ${pow2_result})) 21 | e=$((${e} - 1)) 22 | done 23 | } 24 | 25 | cat < 255) 102 | # error "Too many small size classes" 103 | #endif 104 | 105 | #endif /* JEMALLOC_H_TYPES */ 106 | /******************************************************************************/ 107 | #ifdef JEMALLOC_H_STRUCTS 108 | 109 | 110 | #endif /* JEMALLOC_H_STRUCTS */ 111 | /******************************************************************************/ 112 | #ifdef JEMALLOC_H_EXTERNS 113 | 114 | 115 | #endif /* JEMALLOC_H_EXTERNS */ 116 | /******************************************************************************/ 117 | #ifdef JEMALLOC_H_INLINES 118 | 119 | 120 | #endif /* JEMALLOC_H_INLINES */ 121 | /******************************************************************************/ 122 | EOF 123 | -------------------------------------------------------------------------------- /include/jemalloc/internal/stats.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | typedef struct tcache_bin_stats_s tcache_bin_stats_t; 5 | typedef struct malloc_bin_stats_s malloc_bin_stats_t; 6 | typedef struct malloc_large_stats_s malloc_large_stats_t; 7 | typedef struct arena_stats_s arena_stats_t; 8 | typedef struct chunk_stats_s chunk_stats_t; 9 | 10 | #endif /* JEMALLOC_H_TYPES */ 11 | /******************************************************************************/ 12 | #ifdef JEMALLOC_H_STRUCTS 13 | 14 | struct tcache_bin_stats_s { 15 | /* 16 | * Number of allocation requests that corresponded to the size of this 17 | * bin. 18 | */ 19 | uint64_t nrequests; 20 | }; 21 | 22 | struct malloc_bin_stats_s { 23 | /* 24 | * Current number of bytes allocated, including objects currently 25 | * cached by tcache. 26 | */ 27 | size_t allocated; 28 | 29 | /* 30 | * Total number of allocation/deallocation requests served directly by 31 | * the bin. Note that tcache may allocate an object, then recycle it 32 | * many times, resulting many increments to nrequests, but only one 33 | * each to nmalloc and ndalloc. 34 | */ 35 | uint64_t nmalloc; 36 | uint64_t ndalloc; 37 | 38 | /* 39 | * Number of allocation requests that correspond to the size of this 40 | * bin. This includes requests served by tcache, though tcache only 41 | * periodically merges into this counter. 42 | */ 43 | uint64_t nrequests; 44 | 45 | /* Number of tcache fills from this bin. */ 46 | uint64_t nfills; 47 | 48 | /* Number of tcache flushes to this bin. */ 49 | uint64_t nflushes; 50 | 51 | /* Total number of runs created for this bin's size class. */ 52 | uint64_t nruns; 53 | 54 | /* 55 | * Total number of runs reused by extracting them from the runs tree for 56 | * this bin's size class. 57 | */ 58 | uint64_t reruns; 59 | 60 | /* Current number of runs in this bin. */ 61 | size_t curruns; 62 | }; 63 | 64 | struct malloc_large_stats_s { 65 | /* 66 | * Total number of allocation/deallocation requests served directly by 67 | * the arena. Note that tcache may allocate an object, then recycle it 68 | * many times, resulting many increments to nrequests, but only one 69 | * each to nmalloc and ndalloc. 70 | */ 71 | uint64_t nmalloc; 72 | uint64_t ndalloc; 73 | 74 | /* 75 | * Number of allocation requests that correspond to this size class. 76 | * This includes requests served by tcache, though tcache only 77 | * periodically merges into this counter. 78 | */ 79 | uint64_t nrequests; 80 | 81 | /* Current number of runs of this size class. */ 82 | size_t curruns; 83 | }; 84 | 85 | struct arena_stats_s { 86 | /* Number of bytes currently mapped. */ 87 | size_t mapped; 88 | 89 | /* 90 | * Total number of purge sweeps, total number of madvise calls made, 91 | * and total pages purged in order to keep dirty unused memory under 92 | * control. 93 | */ 94 | uint64_t npurge; 95 | uint64_t nmadvise; 96 | uint64_t purged; 97 | 98 | /* Per-size-category statistics. */ 99 | size_t allocated_large; 100 | uint64_t nmalloc_large; 101 | uint64_t ndalloc_large; 102 | uint64_t nrequests_large; 103 | 104 | /* 105 | * One element for each possible size class, including sizes that 106 | * overlap with bin size classes. This is necessary because ipalloc() 107 | * sometimes has to use such large objects in order to assure proper 108 | * alignment. 109 | */ 110 | malloc_large_stats_t *lstats; 111 | }; 112 | 113 | struct chunk_stats_s { 114 | /* Number of chunks that were allocated. */ 115 | uint64_t nchunks; 116 | 117 | /* High-water mark for number of chunks allocated. */ 118 | size_t highchunks; 119 | 120 | /* 121 | * Current number of chunks allocated. This value isn't maintained for 122 | * any other purpose, so keep track of it in order to be able to set 123 | * highchunks. 124 | */ 125 | size_t curchunks; 126 | }; 127 | 128 | #endif /* JEMALLOC_H_STRUCTS */ 129 | /******************************************************************************/ 130 | #ifdef JEMALLOC_H_EXTERNS 131 | 132 | extern bool opt_stats_print; 133 | 134 | extern size_t stats_cactive; 135 | 136 | void stats_print(void (*write)(void *, const char *), void *cbopaque, 137 | const char *opts); 138 | 139 | #endif /* JEMALLOC_H_EXTERNS */ 140 | /******************************************************************************/ 141 | #ifdef JEMALLOC_H_INLINES 142 | 143 | #ifndef JEMALLOC_ENABLE_INLINE 144 | size_t stats_cactive_get(void); 145 | void stats_cactive_add(size_t size); 146 | void stats_cactive_sub(size_t size); 147 | #endif 148 | 149 | #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_STATS_C_)) 150 | JEMALLOC_INLINE size_t 151 | stats_cactive_get(void) 152 | { 153 | 154 | return (atomic_read_z(&stats_cactive)); 155 | } 156 | 157 | JEMALLOC_INLINE void 158 | stats_cactive_add(size_t size) 159 | { 160 | 161 | atomic_add_z(&stats_cactive, size); 162 | } 163 | 164 | JEMALLOC_INLINE void 165 | stats_cactive_sub(size_t size) 166 | { 167 | 168 | atomic_sub_z(&stats_cactive, size); 169 | } 170 | #endif 171 | 172 | #endif /* JEMALLOC_H_INLINES */ 173 | /******************************************************************************/ 174 | -------------------------------------------------------------------------------- /include/jemalloc/internal/util.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | #ifdef JEMALLOC_H_TYPES 3 | 4 | /* Size of stack-allocated buffer passed to buferror(). */ 5 | #define BUFERROR_BUF 64 6 | 7 | /* 8 | * Size of stack-allocated buffer used by malloc_{,v,vc}printf(). This must be 9 | * large enough for all possible uses within jemalloc. 10 | */ 11 | #define MALLOC_PRINTF_BUFSIZE 4096 12 | 13 | /* 14 | * Wrap a cpp argument that contains commas such that it isn't broken up into 15 | * multiple arguments. 16 | */ 17 | #define JEMALLOC_ARG_CONCAT(...) __VA_ARGS__ 18 | 19 | /* 20 | * Silence compiler warnings due to uninitialized values. This is used 21 | * wherever the compiler fails to recognize that the variable is never used 22 | * uninitialized. 23 | */ 24 | #ifdef JEMALLOC_CC_SILENCE 25 | # define JEMALLOC_CC_SILENCE_INIT(v) = v 26 | #else 27 | # define JEMALLOC_CC_SILENCE_INIT(v) 28 | #endif 29 | 30 | /* 31 | * Define a custom assert() in order to reduce the chances of deadlock during 32 | * assertion failure. 33 | */ 34 | #ifndef assert 35 | #define assert(e) do { \ 36 | if (config_safe && !(e)) { \ 37 | malloc_printf( \ 38 | ": %s:%d: Failed assertion: \"%s\"\n", \ 39 | __FILE__, __LINE__, #e); \ 40 | abort(); \ 41 | } \ 42 | } while (0) 43 | #endif 44 | 45 | #ifndef not_reached 46 | #define not_reached() do { \ 47 | if (config_safe) { \ 48 | malloc_printf( \ 49 | ": %s:%d: Unreachable code reached\n", \ 50 | __FILE__, __LINE__); \ 51 | abort(); \ 52 | } \ 53 | } while (0) 54 | #endif 55 | 56 | #ifndef not_implemented 57 | #define not_implemented() do { \ 58 | if (config_debug) { \ 59 | malloc_printf(": %s:%d: Not implemented\n", \ 60 | __FILE__, __LINE__); \ 61 | abort(); \ 62 | } \ 63 | } while (0) 64 | #endif 65 | 66 | #ifndef assert_not_implemented 67 | #define assert_not_implemented(e) do { \ 68 | if (config_debug && !(e)) \ 69 | not_implemented(); \ 70 | } while (0) 71 | #endif 72 | 73 | /* Use to assert a particular configuration, e.g., cassert(config_debug). */ 74 | #define cassert(c) do { \ 75 | if ((c) == false) \ 76 | not_reached(); \ 77 | } while (0) 78 | 79 | #endif /* JEMALLOC_H_TYPES */ 80 | /******************************************************************************/ 81 | #ifdef JEMALLOC_H_STRUCTS 82 | 83 | #endif /* JEMALLOC_H_STRUCTS */ 84 | /******************************************************************************/ 85 | #ifdef JEMALLOC_H_EXTERNS 86 | 87 | int buferror(int err, char *buf, size_t buflen); 88 | uintmax_t malloc_strtoumax(const char *restrict nptr, 89 | char **restrict endptr, int base); 90 | void malloc_write(const char *s); 91 | 92 | /* 93 | * malloc_vsnprintf() supports a subset of snprintf(3) that avoids floating 94 | * point math. 95 | */ 96 | int malloc_vsnprintf(char *str, size_t size, const char *format, 97 | va_list ap); 98 | int malloc_snprintf(char *str, size_t size, const char *format, ...) 99 | JEMALLOC_ATTR(format(printf, 3, 4)); 100 | void malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque, 101 | const char *format, va_list ap); 102 | void malloc_cprintf(void (*write)(void *, const char *), void *cbopaque, 103 | const char *format, ...) JEMALLOC_ATTR(format(printf, 3, 4)); 104 | void malloc_printf(const char *format, ...) 105 | JEMALLOC_ATTR(format(printf, 1, 2)); 106 | 107 | #endif /* JEMALLOC_H_EXTERNS */ 108 | /******************************************************************************/ 109 | #ifdef JEMALLOC_H_INLINES 110 | 111 | #ifndef JEMALLOC_ENABLE_INLINE 112 | size_t pow2_ceil(size_t x); 113 | void set_errno(int errnum); 114 | int get_errno(void); 115 | #endif 116 | 117 | #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_)) 118 | /* Compute the smallest power of 2 that is >= x. */ 119 | JEMALLOC_INLINE size_t 120 | pow2_ceil(size_t x) 121 | { 122 | 123 | x--; 124 | x |= x >> 1; 125 | x |= x >> 2; 126 | x |= x >> 4; 127 | x |= x >> 8; 128 | x |= x >> 16; 129 | #if (LG_SIZEOF_PTR == 3) 130 | x |= x >> 32; 131 | #endif 132 | x++; 133 | return (x); 134 | } 135 | 136 | /* Sets error code */ 137 | JEMALLOC_INLINE void 138 | set_errno(int errnum) 139 | { 140 | 141 | #ifdef _WIN32 142 | SetLastError(errnum); 143 | #else 144 | errno = errnum; 145 | #endif 146 | } 147 | 148 | /* Get last error code */ 149 | JEMALLOC_INLINE int 150 | get_errno(void) 151 | { 152 | 153 | #ifdef _WIN32 154 | return (GetLastError()); 155 | #else 156 | return (errno); 157 | #endif 158 | } 159 | #endif 160 | 161 | #endif /* JEMALLOC_H_INLINES */ 162 | /******************************************************************************/ 163 | -------------------------------------------------------------------------------- /include/jemalloc/jemalloc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | objroot=$1 4 | 5 | cat < 2 | #include 3 | 4 | #define JEMALLOC_VERSION "@jemalloc_version@" 5 | #define JEMALLOC_VERSION_MAJOR @jemalloc_version_major@ 6 | #define JEMALLOC_VERSION_MINOR @jemalloc_version_minor@ 7 | #define JEMALLOC_VERSION_BUGFIX @jemalloc_version_bugfix@ 8 | #define JEMALLOC_VERSION_NREV @jemalloc_version_nrev@ 9 | #define JEMALLOC_VERSION_GID "@jemalloc_version_gid@" 10 | 11 | # define MALLOCX_LG_ALIGN(la) (la) 12 | # if LG_SIZEOF_PTR == 2 13 | # define MALLOCX_ALIGN(a) (ffs(a)-1) 14 | # else 15 | # define MALLOCX_ALIGN(a) \ 16 | ((a < (size_t)INT_MAX) ? ffs(a)-1 : ffs(a>>32)+31) 17 | # endif 18 | # define MALLOCX_ZERO ((int)0x40) 19 | /* Bias arena index bits so that 0 encodes "MALLOCX_ARENA() unspecified". */ 20 | # define MALLOCX_ARENA(a) ((int)(((a)+1) << 8)) 21 | 22 | #ifdef JEMALLOC_EXPERIMENTAL 23 | # define ALLOCM_LG_ALIGN(la) (la) 24 | # if LG_SIZEOF_PTR == 2 25 | # define ALLOCM_ALIGN(a) (ffs(a)-1) 26 | # else 27 | # define ALLOCM_ALIGN(a) \ 28 | ((a < (size_t)INT_MAX) ? ffs(a)-1 : ffs(a>>32)+31) 29 | # endif 30 | # define ALLOCM_ZERO ((int)0x40) 31 | # define ALLOCM_NO_MOVE ((int)0x80) 32 | /* Bias arena index bits so that 0 encodes "ALLOCM_ARENA() unspecified". */ 33 | # define ALLOCM_ARENA(a) ((int)(((a)+1) << 8)) 34 | # define ALLOCM_SUCCESS 0 35 | # define ALLOCM_ERR_OOM 1 36 | # define ALLOCM_ERR_NOT_MOVED 2 37 | #endif 38 | 39 | #ifdef JEMALLOC_HAVE_ATTR 40 | # define JEMALLOC_ATTR(s) __attribute__((s)) 41 | # define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default")) 42 | # define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s)) 43 | # define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s)) 44 | # define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline) 45 | #elif _MSC_VER 46 | # define JEMALLOC_ATTR(s) 47 | # ifdef DLLEXPORT 48 | # define JEMALLOC_EXPORT __declspec(dllexport) 49 | # else 50 | # define JEMALLOC_EXPORT __declspec(dllimport) 51 | # endif 52 | # define JEMALLOC_ALIGNED(s) __declspec(align(s)) 53 | # define JEMALLOC_SECTION(s) __declspec(allocate(s)) 54 | # define JEMALLOC_NOINLINE __declspec(noinline) 55 | #else 56 | # define JEMALLOC_ATTR(s) 57 | # define JEMALLOC_EXPORT 58 | # define JEMALLOC_ALIGNED(s) 59 | # define JEMALLOC_SECTION(s) 60 | # define JEMALLOC_NOINLINE 61 | #endif 62 | 63 | #ifdef JEMALLOC_ENABLE_MEMKIND 64 | # define JEMALLOC_MEMKIND_FILE_MAPPED (1 << (sizeof(unsigned) * 8 - 1)) 65 | #endif 66 | -------------------------------------------------------------------------------- /include/jemalloc/jemalloc_mangle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | public_symbols_txt=$1 4 | symbol_prefix=$2 5 | 6 | cat < 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 | typedef BOOL _Bool; 9 | 10 | #define bool _Bool 11 | #define true 1 12 | #define false 0 13 | 14 | #define __bool_true_false_are_defined 1 15 | 16 | #endif /* stdbool_h */ 17 | -------------------------------------------------------------------------------- /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 | #include 7 | #pragma intrinsic(_BitScanForward) 8 | static __forceinline int ffsl(long x) 9 | { 10 | unsigned long i; 11 | 12 | if (_BitScanForward(&i, x)) 13 | return (i + 1); 14 | return (0); 15 | } 16 | 17 | static __forceinline int ffs(int x) 18 | { 19 | 20 | return (ffsl(x)); 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/atomic.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_ATOMIC_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | -------------------------------------------------------------------------------- /src/base.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_BASE_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | /******************************************************************************/ 5 | /* Data. */ 6 | 7 | static malloc_mutex_t base_mtx; 8 | 9 | /* 10 | * Current pages that are being used for internal memory allocations. These 11 | * pages are carved up in cacheline-size quanta, so that there is no chance of 12 | * false cache line sharing. 13 | */ 14 | static void *base_pages; 15 | static void *base_next_addr; 16 | static void *base_past_addr; /* Addr immediately past base_pages. */ 17 | static extent_node_t *base_nodes; 18 | 19 | /******************************************************************************/ 20 | /* Function prototypes for non-inline static functions. */ 21 | 22 | static bool base_pages_alloc(size_t minsize); 23 | 24 | /******************************************************************************/ 25 | 26 | static bool 27 | base_pages_alloc(size_t minsize) 28 | { 29 | size_t csize; 30 | bool zero; 31 | 32 | assert(minsize != 0); 33 | csize = CHUNK_CEILING(minsize); 34 | zero = false; 35 | base_pages = chunk_alloc(csize, chunksize, true, &zero, 36 | chunk_dss_prec_get() 37 | #ifdef JEMALLOC_ENABLE_MEMKIND 38 | , 0 39 | #endif 40 | ); 41 | if (base_pages == NULL) 42 | return (true); 43 | base_next_addr = base_pages; 44 | base_past_addr = (void *)((uintptr_t)base_pages + csize); 45 | 46 | return (false); 47 | } 48 | 49 | void * 50 | base_alloc(size_t size) 51 | { 52 | void *ret; 53 | size_t csize; 54 | 55 | /* Round size up to nearest multiple of the cacheline size. */ 56 | csize = CACHELINE_CEILING(size); 57 | 58 | malloc_mutex_lock(&base_mtx); 59 | /* Make sure there's enough space for the allocation. */ 60 | if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) { 61 | if (base_pages_alloc(csize)) { 62 | malloc_mutex_unlock(&base_mtx); 63 | return (NULL); 64 | } 65 | } 66 | /* Allocate. */ 67 | ret = base_next_addr; 68 | base_next_addr = (void *)((uintptr_t)base_next_addr + csize); 69 | malloc_mutex_unlock(&base_mtx); 70 | VALGRIND_MAKE_MEM_UNDEFINED(ret, csize); 71 | 72 | return (ret); 73 | } 74 | 75 | void * 76 | base_calloc(size_t number, size_t size) 77 | { 78 | void *ret = base_alloc(number * size); 79 | 80 | if (ret != NULL) 81 | memset(ret, 0, number * size); 82 | 83 | return (ret); 84 | } 85 | 86 | extent_node_t * 87 | base_node_alloc(void) 88 | { 89 | extent_node_t *ret; 90 | 91 | malloc_mutex_lock(&base_mtx); 92 | if (base_nodes != NULL) { 93 | ret = base_nodes; 94 | base_nodes = *(extent_node_t **)ret; 95 | malloc_mutex_unlock(&base_mtx); 96 | VALGRIND_MAKE_MEM_UNDEFINED(ret, sizeof(extent_node_t)); 97 | } else { 98 | malloc_mutex_unlock(&base_mtx); 99 | ret = (extent_node_t *)base_alloc(sizeof(extent_node_t)); 100 | } 101 | 102 | return (ret); 103 | } 104 | 105 | void 106 | base_node_dealloc(extent_node_t *node) 107 | { 108 | 109 | VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t)); 110 | malloc_mutex_lock(&base_mtx); 111 | *(extent_node_t **)node = base_nodes; 112 | base_nodes = node; 113 | malloc_mutex_unlock(&base_mtx); 114 | } 115 | 116 | bool 117 | base_boot(void) 118 | { 119 | 120 | base_nodes = NULL; 121 | if (malloc_mutex_init(&base_mtx)) 122 | return (true); 123 | 124 | return (false); 125 | } 126 | 127 | void 128 | base_prefork(void) 129 | { 130 | 131 | malloc_mutex_prefork(&base_mtx); 132 | } 133 | 134 | void 135 | base_postfork_parent(void) 136 | { 137 | 138 | malloc_mutex_postfork_parent(&base_mtx); 139 | } 140 | 141 | void 142 | base_postfork_child(void) 143 | { 144 | 145 | malloc_mutex_postfork_child(&base_mtx); 146 | } 147 | -------------------------------------------------------------------------------- /src/bitmap.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_BITMAP_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | /******************************************************************************/ 5 | /* Function prototypes for non-inline static functions. */ 6 | 7 | static size_t bits2groups(size_t nbits); 8 | 9 | /******************************************************************************/ 10 | 11 | static size_t 12 | bits2groups(size_t nbits) 13 | { 14 | 15 | return ((nbits >> LG_BITMAP_GROUP_NBITS) + 16 | !!(nbits & BITMAP_GROUP_NBITS_MASK)); 17 | } 18 | 19 | void 20 | bitmap_info_init(bitmap_info_t *binfo, size_t nbits) 21 | { 22 | unsigned i; 23 | size_t group_count; 24 | 25 | assert(nbits > 0); 26 | assert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS)); 27 | 28 | /* 29 | * Compute the number of groups necessary to store nbits bits, and 30 | * progressively work upward through the levels until reaching a level 31 | * that requires only one group. 32 | */ 33 | binfo->levels[0].group_offset = 0; 34 | group_count = bits2groups(nbits); 35 | for (i = 1; group_count > 1; i++) { 36 | assert(i < BITMAP_MAX_LEVELS); 37 | binfo->levels[i].group_offset = binfo->levels[i-1].group_offset 38 | + group_count; 39 | group_count = bits2groups(group_count); 40 | } 41 | binfo->levels[i].group_offset = binfo->levels[i-1].group_offset 42 | + group_count; 43 | binfo->nlevels = i; 44 | binfo->nbits = nbits; 45 | } 46 | 47 | size_t 48 | bitmap_info_ngroups(const bitmap_info_t *binfo) 49 | { 50 | 51 | return (binfo->levels[binfo->nlevels].group_offset << LG_SIZEOF_BITMAP); 52 | } 53 | 54 | size_t 55 | bitmap_size(size_t nbits) 56 | { 57 | bitmap_info_t binfo; 58 | 59 | bitmap_info_init(&binfo, nbits); 60 | return (bitmap_info_ngroups(&binfo)); 61 | } 62 | 63 | void 64 | bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo) 65 | { 66 | size_t extra; 67 | unsigned i; 68 | 69 | /* 70 | * Bits are actually inverted with regard to the external bitmap 71 | * interface, so the bitmap starts out with all 1 bits, except for 72 | * trailing unused bits (if any). Note that each group uses bit 0 to 73 | * correspond to the first logical bit in the group, so extra bits 74 | * are the most significant bits of the last group. 75 | */ 76 | memset(bitmap, 0xffU, binfo->levels[binfo->nlevels].group_offset << 77 | LG_SIZEOF_BITMAP); 78 | extra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK)) 79 | & BITMAP_GROUP_NBITS_MASK; 80 | if (extra != 0) 81 | bitmap[binfo->levels[1].group_offset - 1] >>= extra; 82 | for (i = 1; i < binfo->nlevels; i++) { 83 | size_t group_count = binfo->levels[i].group_offset - 84 | binfo->levels[i-1].group_offset; 85 | extra = (BITMAP_GROUP_NBITS - (group_count & 86 | BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK; 87 | if (extra != 0) 88 | bitmap[binfo->levels[i+1].group_offset - 1] >>= extra; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/chunk_dss.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_CHUNK_DSS_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | /******************************************************************************/ 4 | /* Data. */ 5 | 6 | const char *dss_prec_names[] = { 7 | "disabled", 8 | "primary", 9 | "secondary", 10 | "N/A" 11 | }; 12 | 13 | /* Current dss precedence default, used when creating new arenas. */ 14 | static dss_prec_t dss_prec_default = DSS_PREC_DEFAULT; 15 | 16 | /* 17 | * Protects sbrk() calls. This avoids malloc races among threads, though it 18 | * does not protect against races with threads that call sbrk() directly. 19 | */ 20 | static malloc_mutex_t dss_mtx; 21 | 22 | /* Base address of the DSS. */ 23 | static void *dss_base; 24 | /* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */ 25 | static void *dss_prev; 26 | /* Current upper limit on DSS addresses. */ 27 | static void *dss_max; 28 | 29 | /******************************************************************************/ 30 | 31 | static void * 32 | chunk_dss_sbrk(intptr_t increment) 33 | { 34 | 35 | #ifdef JEMALLOC_HAVE_SBRK 36 | return (sbrk(increment)); 37 | #else 38 | not_implemented(); 39 | return (NULL); 40 | #endif 41 | } 42 | 43 | dss_prec_t 44 | chunk_dss_prec_get(void) 45 | { 46 | dss_prec_t ret; 47 | 48 | if (config_dss == false) 49 | return (dss_prec_disabled); 50 | malloc_mutex_lock(&dss_mtx); 51 | ret = dss_prec_default; 52 | malloc_mutex_unlock(&dss_mtx); 53 | return (ret); 54 | } 55 | 56 | bool 57 | chunk_dss_prec_set(dss_prec_t dss_prec) 58 | { 59 | 60 | if (config_dss == false) 61 | return (true); 62 | malloc_mutex_lock(&dss_mtx); 63 | dss_prec_default = dss_prec; 64 | malloc_mutex_unlock(&dss_mtx); 65 | return (false); 66 | } 67 | 68 | void * 69 | chunk_alloc_dss(size_t size, size_t alignment, bool *zero) 70 | { 71 | void *ret; 72 | 73 | cassert(config_dss); 74 | assert(size > 0 && (size & chunksize_mask) == 0); 75 | assert(alignment > 0 && (alignment & chunksize_mask) == 0); 76 | 77 | /* 78 | * sbrk() uses a signed increment argument, so take care not to 79 | * interpret a huge allocation request as a negative increment. 80 | */ 81 | if ((intptr_t)size < 0) 82 | return (NULL); 83 | 84 | malloc_mutex_lock(&dss_mtx); 85 | if (dss_prev != (void *)-1) { 86 | size_t gap_size, cpad_size; 87 | void *cpad, *dss_next; 88 | intptr_t incr; 89 | 90 | /* 91 | * The loop is necessary to recover from races with other 92 | * threads that are using the DSS for something other than 93 | * malloc. 94 | */ 95 | do { 96 | /* Get the current end of the DSS. */ 97 | dss_max = chunk_dss_sbrk(0); 98 | /* 99 | * Calculate how much padding is necessary to 100 | * chunk-align the end of the DSS. 101 | */ 102 | gap_size = (chunksize - CHUNK_ADDR2OFFSET(dss_max)) & 103 | chunksize_mask; 104 | /* 105 | * Compute how much chunk-aligned pad space (if any) is 106 | * necessary to satisfy alignment. This space can be 107 | * recycled for later use. 108 | */ 109 | cpad = (void *)((uintptr_t)dss_max + gap_size); 110 | ret = (void *)ALIGNMENT_CEILING((uintptr_t)dss_max, 111 | alignment); 112 | cpad_size = (uintptr_t)ret - (uintptr_t)cpad; 113 | dss_next = (void *)((uintptr_t)ret + size); 114 | if ((uintptr_t)ret < (uintptr_t)dss_max || 115 | (uintptr_t)dss_next < (uintptr_t)dss_max) { 116 | /* Wrap-around. */ 117 | malloc_mutex_unlock(&dss_mtx); 118 | return (NULL); 119 | } 120 | incr = gap_size + cpad_size + size; 121 | dss_prev = chunk_dss_sbrk(incr); 122 | if (dss_prev == dss_max) { 123 | /* Success. */ 124 | dss_max = dss_next; 125 | malloc_mutex_unlock(&dss_mtx); 126 | if (cpad_size != 0) 127 | chunk_unmap(cpad, cpad_size 128 | #ifdef JEMALLOC_ENABLE_MEMKIND 129 | , 0 130 | #endif 131 | ); 132 | if (*zero) { 133 | VALGRIND_MAKE_MEM_UNDEFINED(ret, size); 134 | memset(ret, 0, size); 135 | } 136 | return (ret); 137 | } 138 | } while (dss_prev != (void *)-1); 139 | } 140 | malloc_mutex_unlock(&dss_mtx); 141 | 142 | return (NULL); 143 | } 144 | 145 | bool 146 | chunk_in_dss(void *chunk) 147 | { 148 | bool ret; 149 | 150 | cassert(config_dss); 151 | 152 | malloc_mutex_lock(&dss_mtx); 153 | if ((uintptr_t)chunk >= (uintptr_t)dss_base 154 | && (uintptr_t)chunk < (uintptr_t)dss_max) 155 | ret = true; 156 | else 157 | ret = false; 158 | malloc_mutex_unlock(&dss_mtx); 159 | 160 | return (ret); 161 | } 162 | 163 | bool 164 | chunk_dss_boot(void) 165 | { 166 | 167 | cassert(config_dss); 168 | 169 | if (malloc_mutex_init(&dss_mtx)) 170 | return (true); 171 | dss_base = chunk_dss_sbrk(0); 172 | dss_prev = dss_base; 173 | dss_max = dss_base; 174 | 175 | return (false); 176 | } 177 | 178 | void 179 | chunk_dss_prefork(void) 180 | { 181 | 182 | if (config_dss) 183 | malloc_mutex_prefork(&dss_mtx); 184 | } 185 | 186 | void 187 | chunk_dss_postfork_parent(void) 188 | { 189 | 190 | if (config_dss) 191 | malloc_mutex_postfork_parent(&dss_mtx); 192 | } 193 | 194 | void 195 | chunk_dss_postfork_child(void) 196 | { 197 | 198 | if (config_dss) 199 | malloc_mutex_postfork_child(&dss_mtx); 200 | } 201 | 202 | /******************************************************************************/ 203 | -------------------------------------------------------------------------------- /src/extent.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_EXTENT_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | /******************************************************************************/ 5 | 6 | static inline int 7 | extent_szad_comp(extent_node_t *a, extent_node_t *b) 8 | { 9 | int ret; 10 | #ifdef JEMALLOC_ENABLE_MEMKIND 11 | unsigned a_partition = a->partition; 12 | unsigned b_partition = b->partition; 13 | 14 | ret = (a_partition > b_partition) - (a_partition < b_partition); 15 | 16 | if (ret == 0) { 17 | #endif 18 | size_t a_size = a->size; 19 | size_t b_size = b->size; 20 | 21 | ret = (a_size > b_size) - (a_size < b_size); 22 | if (ret == 0) { 23 | uintptr_t a_addr = (uintptr_t)a->addr; 24 | uintptr_t b_addr = (uintptr_t)b->addr; 25 | 26 | ret = (a_addr > b_addr) - (a_addr < b_addr); 27 | } 28 | #ifdef JEMALLOC_ENABLE_MEMKIND 29 | } 30 | #endif 31 | 32 | return (ret); 33 | } 34 | 35 | /* Generate red-black tree functions. */ 36 | rb_gen(, extent_tree_szad_, extent_tree_t, extent_node_t, link_szad, 37 | extent_szad_comp) 38 | 39 | static inline int 40 | extent_ad_comp(extent_node_t *a, extent_node_t *b) 41 | { 42 | int ret; 43 | #ifdef JEMALLOC_ENABLE_MEMKIND 44 | unsigned a_partition = a->partition; 45 | unsigned b_partition = b->partition; 46 | 47 | ret = (a_partition > b_partition) - (a_partition < b_partition); 48 | 49 | if (ret == 0) { 50 | #endif 51 | uintptr_t a_addr = (uintptr_t)a->addr; 52 | uintptr_t b_addr = (uintptr_t)b->addr; 53 | 54 | ret = (a_addr > b_addr) - (a_addr < b_addr); 55 | #ifdef JEMALLOC_ENABLE_MEMKIND 56 | } 57 | #endif 58 | 59 | return (ret); 60 | } 61 | 62 | /* Generate red-black tree functions. */ 63 | rb_gen(, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad, 64 | extent_ad_comp) 65 | -------------------------------------------------------------------------------- /src/hash.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_HASH_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | -------------------------------------------------------------------------------- /src/mb.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_MB_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | -------------------------------------------------------------------------------- /src/mutex.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_MUTEX_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) 5 | #include 6 | #endif 7 | 8 | #ifndef _CRT_SPINCOUNT 9 | #define _CRT_SPINCOUNT 4000 10 | #endif 11 | 12 | /******************************************************************************/ 13 | /* Data. */ 14 | 15 | #ifdef JEMALLOC_LAZY_LOCK 16 | bool isthreaded = false; 17 | #endif 18 | #ifdef JEMALLOC_MUTEX_INIT_CB 19 | static bool postpone_init = true; 20 | static malloc_mutex_t *postponed_mutexes = NULL; 21 | #endif 22 | 23 | #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) 24 | static void pthread_create_once(void); 25 | #endif 26 | 27 | /******************************************************************************/ 28 | /* 29 | * We intercept pthread_create() calls in order to toggle isthreaded if the 30 | * process goes multi-threaded. 31 | */ 32 | 33 | #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) 34 | static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *, 35 | void *(*)(void *), void *__restrict); 36 | 37 | static void 38 | pthread_create_once(void) 39 | { 40 | 41 | pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create"); 42 | if (pthread_create_fptr == NULL) { 43 | malloc_write(": Error in dlsym(RTLD_NEXT, " 44 | "\"pthread_create\")\n"); 45 | abort(); 46 | } 47 | 48 | isthreaded = true; 49 | } 50 | 51 | JEMALLOC_EXPORT int 52 | pthread_create(pthread_t *__restrict thread, 53 | const pthread_attr_t *__restrict attr, void *(*start_routine)(void *), 54 | void *__restrict arg) 55 | { 56 | static pthread_once_t once_control = PTHREAD_ONCE_INIT; 57 | 58 | pthread_once(&once_control, pthread_create_once); 59 | 60 | return (pthread_create_fptr(thread, attr, start_routine, arg)); 61 | } 62 | #endif 63 | 64 | /******************************************************************************/ 65 | 66 | #ifdef JEMALLOC_MUTEX_INIT_CB 67 | JEMALLOC_EXPORT int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, 68 | void *(calloc_cb)(size_t, size_t)); 69 | #endif 70 | 71 | bool 72 | malloc_mutex_init(malloc_mutex_t *mutex) 73 | { 74 | 75 | #ifdef _WIN32 76 | if (!InitializeCriticalSectionAndSpinCount(&mutex->lock, 77 | _CRT_SPINCOUNT)) 78 | return (true); 79 | #elif (defined(JEMALLOC_OSSPIN)) 80 | mutex->lock = 0; 81 | #elif (defined(JEMALLOC_MUTEX_INIT_CB)) 82 | if (postpone_init) { 83 | mutex->postponed_next = postponed_mutexes; 84 | postponed_mutexes = mutex; 85 | } else { 86 | if (_pthread_mutex_init_calloc_cb(&mutex->lock, base_calloc) != 87 | 0) 88 | return (true); 89 | } 90 | #else 91 | pthread_mutexattr_t attr; 92 | 93 | if (pthread_mutexattr_init(&attr) != 0) 94 | return (true); 95 | pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE); 96 | if (pthread_mutex_init(&mutex->lock, &attr) != 0) { 97 | pthread_mutexattr_destroy(&attr); 98 | return (true); 99 | } 100 | pthread_mutexattr_destroy(&attr); 101 | #endif 102 | return (false); 103 | } 104 | 105 | void 106 | malloc_mutex_prefork(malloc_mutex_t *mutex) 107 | { 108 | 109 | malloc_mutex_lock(mutex); 110 | } 111 | 112 | void 113 | malloc_mutex_postfork_parent(malloc_mutex_t *mutex) 114 | { 115 | 116 | malloc_mutex_unlock(mutex); 117 | } 118 | 119 | void 120 | malloc_mutex_postfork_child(malloc_mutex_t *mutex) 121 | { 122 | 123 | #ifdef JEMALLOC_MUTEX_INIT_CB 124 | malloc_mutex_unlock(mutex); 125 | #else 126 | if (malloc_mutex_init(mutex)) { 127 | malloc_printf(": Error re-initializing mutex in " 128 | "child\n"); 129 | if (opt_abort) 130 | abort(); 131 | } 132 | #endif 133 | } 134 | 135 | bool 136 | mutex_boot(void) 137 | { 138 | 139 | #ifdef JEMALLOC_MUTEX_INIT_CB 140 | postpone_init = false; 141 | while (postponed_mutexes != NULL) { 142 | if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock, 143 | base_calloc) != 0) 144 | return (true); 145 | postponed_mutexes = postponed_mutexes->postponed_next; 146 | } 147 | #endif 148 | return (false); 149 | } 150 | -------------------------------------------------------------------------------- /src/rtree.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_RTREE_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | rtree_t * 5 | rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc) 6 | { 7 | rtree_t *ret; 8 | unsigned bits_per_level, bits_in_leaf, height, i; 9 | 10 | assert(bits > 0 && bits <= (sizeof(uintptr_t) << 3)); 11 | 12 | bits_per_level = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(void *)))) - 1; 13 | bits_in_leaf = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(uint8_t)))) - 1; 14 | if (bits > bits_in_leaf) { 15 | height = 1 + (bits - bits_in_leaf) / bits_per_level; 16 | if ((height-1) * bits_per_level + bits_in_leaf != bits) 17 | height++; 18 | } else { 19 | height = 1; 20 | } 21 | assert((height-1) * bits_per_level + bits_in_leaf >= bits); 22 | 23 | ret = (rtree_t*)alloc(offsetof(rtree_t, level2bits) + 24 | (sizeof(unsigned) * height)); 25 | if (ret == NULL) 26 | return (NULL); 27 | memset(ret, 0, offsetof(rtree_t, level2bits) + (sizeof(unsigned) * 28 | height)); 29 | 30 | ret->alloc = alloc; 31 | ret->dalloc = dalloc; 32 | if (malloc_mutex_init(&ret->mutex)) { 33 | if (dalloc != NULL) 34 | dalloc(ret); 35 | return (NULL); 36 | } 37 | ret->height = height; 38 | if (height > 1) { 39 | if ((height-1) * bits_per_level + bits_in_leaf > bits) { 40 | ret->level2bits[0] = (bits - bits_in_leaf) % 41 | bits_per_level; 42 | } else 43 | ret->level2bits[0] = bits_per_level; 44 | for (i = 1; i < height-1; i++) 45 | ret->level2bits[i] = bits_per_level; 46 | ret->level2bits[height-1] = bits_in_leaf; 47 | } else 48 | ret->level2bits[0] = bits; 49 | 50 | ret->root = (void**)alloc(sizeof(void *) << ret->level2bits[0]); 51 | if (ret->root == NULL) { 52 | if (dalloc != NULL) 53 | dalloc(ret); 54 | return (NULL); 55 | } 56 | memset(ret->root, 0, sizeof(void *) << ret->level2bits[0]); 57 | 58 | return (ret); 59 | } 60 | 61 | static void 62 | rtree_delete_subtree(rtree_t *rtree, void **node, unsigned level) 63 | { 64 | 65 | if (level < rtree->height - 1) { 66 | size_t nchildren, i; 67 | 68 | nchildren = ZU(1) << rtree->level2bits[level]; 69 | for (i = 0; i < nchildren; i++) { 70 | void **child = (void **)node[i]; 71 | if (child != NULL) 72 | rtree_delete_subtree(rtree, child, level + 1); 73 | } 74 | } 75 | rtree->dalloc(node); 76 | } 77 | 78 | void 79 | rtree_delete(rtree_t *rtree) 80 | { 81 | 82 | rtree_delete_subtree(rtree, rtree->root, 0); 83 | rtree->dalloc(rtree); 84 | } 85 | 86 | void 87 | rtree_prefork(rtree_t *rtree) 88 | { 89 | 90 | malloc_mutex_prefork(&rtree->mutex); 91 | } 92 | 93 | void 94 | rtree_postfork_parent(rtree_t *rtree) 95 | { 96 | 97 | malloc_mutex_postfork_parent(&rtree->mutex); 98 | } 99 | 100 | void 101 | rtree_postfork_child(rtree_t *rtree) 102 | { 103 | 104 | malloc_mutex_postfork_child(&rtree->mutex); 105 | } 106 | -------------------------------------------------------------------------------- /src/tsd.c: -------------------------------------------------------------------------------- 1 | #define JEMALLOC_TSD_C_ 2 | #include "jemalloc/internal/jemalloc_internal.h" 3 | 4 | /******************************************************************************/ 5 | /* Data. */ 6 | 7 | static unsigned ncleanups; 8 | static malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX]; 9 | 10 | /******************************************************************************/ 11 | 12 | void * 13 | malloc_tsd_malloc(size_t size) 14 | { 15 | 16 | /* Avoid choose_arena() in order to dodge bootstrapping issues. */ 17 | return (arena_malloc(arenas[0], size, false, false)); 18 | } 19 | 20 | void 21 | malloc_tsd_dalloc(void *wrapper) 22 | { 23 | 24 | idalloct(wrapper, false); 25 | } 26 | 27 | void 28 | malloc_tsd_no_cleanup(void *arg) 29 | { 30 | 31 | not_reached(); 32 | } 33 | 34 | #if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32) 35 | #ifndef _WIN32 36 | JEMALLOC_EXPORT 37 | #endif 38 | void 39 | _malloc_thread_cleanup(void) 40 | { 41 | bool pending[MALLOC_TSD_CLEANUPS_MAX], again; 42 | unsigned i; 43 | 44 | for (i = 0; i < ncleanups; i++) 45 | pending[i] = true; 46 | 47 | do { 48 | again = false; 49 | for (i = 0; i < ncleanups; i++) { 50 | if (pending[i]) { 51 | pending[i] = cleanups[i](); 52 | if (pending[i]) 53 | again = true; 54 | } 55 | } 56 | } while (again); 57 | } 58 | #endif 59 | 60 | void 61 | malloc_tsd_cleanup_register(bool (*f)(void)) 62 | { 63 | 64 | assert(ncleanups < MALLOC_TSD_CLEANUPS_MAX); 65 | cleanups[ncleanups] = f; 66 | ncleanups++; 67 | } 68 | 69 | void 70 | malloc_tsd_boot(void) 71 | { 72 | 73 | ncleanups = 0; 74 | } 75 | 76 | #ifdef _WIN32 77 | static BOOL WINAPI 78 | _tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 79 | { 80 | 81 | switch (fdwReason) { 82 | #ifdef JEMALLOC_LAZY_LOCK 83 | case DLL_THREAD_ATTACH: 84 | isthreaded = true; 85 | break; 86 | #endif 87 | case DLL_THREAD_DETACH: 88 | _malloc_thread_cleanup(); 89 | break; 90 | default: 91 | break; 92 | } 93 | return (true); 94 | } 95 | 96 | #ifdef _MSC_VER 97 | # ifdef _M_IX86 98 | # pragma comment(linker, "/INCLUDE:__tls_used") 99 | # else 100 | # pragma comment(linker, "/INCLUDE:_tls_used") 101 | # endif 102 | # pragma section(".CRT$XLY",long,read) 103 | #endif 104 | JEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used) 105 | static const BOOL (WINAPI *tls_callback)(HINSTANCE hinstDLL, 106 | DWORD fdwReason, LPVOID lpvReserved) = _tls_callback; 107 | #endif 108 | 109 | #if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \ 110 | !defined(_WIN32)) 111 | void * 112 | tsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block) 113 | { 114 | pthread_t self = pthread_self(); 115 | tsd_init_block_t *iter; 116 | 117 | /* Check whether this thread has already inserted into the list. */ 118 | malloc_mutex_lock(&head->lock); 119 | ql_foreach(iter, &head->blocks, link) { 120 | if (iter->thread == self) { 121 | malloc_mutex_unlock(&head->lock); 122 | return (iter->data); 123 | } 124 | } 125 | /* Insert block into list. */ 126 | ql_elm_new(block, link); 127 | block->thread = self; 128 | ql_tail_insert(&head->blocks, block, link); 129 | malloc_mutex_unlock(&head->lock); 130 | return (NULL); 131 | } 132 | 133 | void 134 | tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block) 135 | { 136 | 137 | malloc_mutex_lock(&head->lock); 138 | ql_remove(&head->blocks, block, link); 139 | malloc_mutex_unlock(&head->lock); 140 | } 141 | #endif 142 | -------------------------------------------------------------------------------- /test/include/test/SFMT-params.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_PARAMS_H 37 | #define SFMT_PARAMS_H 38 | 39 | #if !defined(MEXP) 40 | #ifdef __GNUC__ 41 | #warning "MEXP is not defined. I assume MEXP is 19937." 42 | #endif 43 | #define MEXP 19937 44 | #endif 45 | /*----------------- 46 | BASIC DEFINITIONS 47 | -----------------*/ 48 | /** Mersenne Exponent. The period of the sequence 49 | * is a multiple of 2^MEXP-1. 50 | * #define MEXP 19937 */ 51 | /** SFMT generator has an internal state array of 128-bit integers, 52 | * and N is its size. */ 53 | #define N (MEXP / 128 + 1) 54 | /** N32 is the size of internal state array when regarded as an array 55 | * of 32-bit integers.*/ 56 | #define N32 (N * 4) 57 | /** N64 is the size of internal state array when regarded as an array 58 | * of 64-bit integers.*/ 59 | #define N64 (N * 2) 60 | 61 | /*---------------------- 62 | the parameters of SFMT 63 | following definitions are in paramsXXXX.h file. 64 | ----------------------*/ 65 | /** the pick up position of the array. 66 | #define POS1 122 67 | */ 68 | 69 | /** the parameter of shift left as four 32-bit registers. 70 | #define SL1 18 71 | */ 72 | 73 | /** the parameter of shift left as one 128-bit register. 74 | * The 128-bit integer is shifted by (SL2 * 8) bits. 75 | #define SL2 1 76 | */ 77 | 78 | /** the parameter of shift right as four 32-bit registers. 79 | #define SR1 11 80 | */ 81 | 82 | /** the parameter of shift right as one 128-bit register. 83 | * The 128-bit integer is shifted by (SL2 * 8) bits. 84 | #define SR2 1 85 | */ 86 | 87 | /** A bitmask, used in the recursion. These parameters are introduced 88 | * to break symmetry of SIMD. 89 | #define MSK1 0xdfffffefU 90 | #define MSK2 0xddfecb7fU 91 | #define MSK3 0xbffaffffU 92 | #define MSK4 0xbffffff6U 93 | */ 94 | 95 | /** These definitions are part of a 128-bit period certification vector. 96 | #define PARITY1 0x00000001U 97 | #define PARITY2 0x00000000U 98 | #define PARITY3 0x00000000U 99 | #define PARITY4 0xc98e126aU 100 | */ 101 | 102 | #if MEXP == 607 103 | #include "test/SFMT-params607.h" 104 | #elif MEXP == 1279 105 | #include "test/SFMT-params1279.h" 106 | #elif MEXP == 2281 107 | #include "test/SFMT-params2281.h" 108 | #elif MEXP == 4253 109 | #include "test/SFMT-params4253.h" 110 | #elif MEXP == 11213 111 | #include "test/SFMT-params11213.h" 112 | #elif MEXP == 19937 113 | #include "test/SFMT-params19937.h" 114 | #elif MEXP == 44497 115 | #include "test/SFMT-params44497.h" 116 | #elif MEXP == 86243 117 | #include "test/SFMT-params86243.h" 118 | #elif MEXP == 132049 119 | #include "test/SFMT-params132049.h" 120 | #elif MEXP == 216091 121 | #include "test/SFMT-params216091.h" 122 | #else 123 | #ifdef __GNUC__ 124 | #error "MEXP is not valid." 125 | #undef MEXP 126 | #else 127 | #undef MEXP 128 | #endif 129 | 130 | #endif 131 | 132 | #endif /* SFMT_PARAMS_H */ 133 | -------------------------------------------------------------------------------- /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-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-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-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-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/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-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-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-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/jemalloc_test.h.in: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef _WIN32 10 | # include 11 | #else 12 | # include 13 | #endif 14 | 15 | /******************************************************************************/ 16 | /* 17 | * Define always-enabled assertion macros, so that test assertions execute even 18 | * if assertions are disabled in the library code. These definitions must 19 | * exist prior to including "jemalloc/internal/util.h". 20 | */ 21 | #define assert(e) do { \ 22 | if (!(e)) { \ 23 | malloc_printf( \ 24 | ": %s:%d: Failed assertion: \"%s\"\n", \ 25 | __FILE__, __LINE__, #e); \ 26 | abort(); \ 27 | } \ 28 | } while (0) 29 | 30 | #define not_reached() do { \ 31 | malloc_printf( \ 32 | ": %s:%d: Unreachable code reached\n", \ 33 | __FILE__, __LINE__); \ 34 | abort(); \ 35 | } while (0) 36 | 37 | #define not_implemented() do { \ 38 | malloc_printf(": %s:%d: Not implemented\n", \ 39 | __FILE__, __LINE__); \ 40 | abort(); \ 41 | } while (0) 42 | 43 | #define assert_not_implemented(e) do { \ 44 | if (!(e)) \ 45 | not_implemented(); \ 46 | } while (0) 47 | 48 | #include "test/jemalloc_test_defs.h" 49 | 50 | #ifdef JEMALLOC_OSSPIN 51 | # include 52 | #endif 53 | 54 | #if defined(HAVE_ALTIVEC) && !defined(__APPLE__) 55 | # include 56 | #endif 57 | #ifdef HAVE_SSE2 58 | # include 59 | #endif 60 | 61 | /******************************************************************************/ 62 | /* 63 | * For unit tests, expose all public and private interfaces. 64 | */ 65 | #ifdef JEMALLOC_UNIT_TEST 66 | # define JEMALLOC_JET 67 | # define JEMALLOC_MANGLE 68 | # include "jemalloc/internal/jemalloc_internal.h" 69 | 70 | /******************************************************************************/ 71 | /* 72 | * For integration tests, expose the public jemalloc interfaces, but only 73 | * expose the minimum necessary internal utility code (to avoid re-implementing 74 | * essentially identical code within the test infrastructure). 75 | */ 76 | #elif defined(JEMALLOC_INTEGRATION_TEST) 77 | # define JEMALLOC_MANGLE 78 | # include "jemalloc/jemalloc@install_suffix@.h" 79 | # include "jemalloc/internal/jemalloc_internal_defs.h" 80 | # include "jemalloc/internal/jemalloc_internal_macros.h" 81 | 82 | # define JEMALLOC_N(n) @private_namespace@##n 83 | # include "jemalloc/internal/private_namespace.h" 84 | 85 | # define JEMALLOC_H_TYPES 86 | # define JEMALLOC_H_STRUCTS 87 | # define JEMALLOC_H_EXTERNS 88 | # define JEMALLOC_H_INLINES 89 | # include "jemalloc/internal/util.h" 90 | # include "jemalloc/internal/qr.h" 91 | # include "jemalloc/internal/ql.h" 92 | # undef JEMALLOC_H_TYPES 93 | # undef JEMALLOC_H_STRUCTS 94 | # undef JEMALLOC_H_EXTERNS 95 | # undef JEMALLOC_H_INLINES 96 | 97 | /******************************************************************************/ 98 | /* 99 | * For stress tests, expose the public jemalloc interfaces with name mangling 100 | * so that they can be tested as e.g. malloc() and free(). Also expose the 101 | * public jemalloc interfaces with jet_ prefixes, so that stress tests can use 102 | * a separate allocator for their internal data structures. 103 | */ 104 | #elif defined(JEMALLOC_STRESS_TEST) 105 | # include "jemalloc/jemalloc@install_suffix@.h" 106 | 107 | # include "jemalloc/jemalloc_protos_jet.h" 108 | 109 | # define JEMALLOC_JET 110 | # include "jemalloc/internal/jemalloc_internal.h" 111 | # include "jemalloc/internal/public_unnamespace.h" 112 | # undef JEMALLOC_JET 113 | 114 | # include "jemalloc/jemalloc_rename.h" 115 | # define JEMALLOC_MANGLE 116 | # ifdef JEMALLOC_STRESS_TESTLIB 117 | # include "jemalloc/jemalloc_mangle_jet.h" 118 | # else 119 | # include "jemalloc/jemalloc_mangle.h" 120 | # endif 121 | 122 | /******************************************************************************/ 123 | /* 124 | * This header does dangerous things, the effects of which only test code 125 | * should be subject to. 126 | */ 127 | #else 128 | # error "This header cannot be included outside a testing context" 129 | #endif 130 | 131 | /******************************************************************************/ 132 | /* 133 | * Common test utilities. 134 | */ 135 | #include "test/math.h" 136 | #include "test/mtx.h" 137 | #include "test/mq.h" 138 | #include "test/test.h" 139 | #include "test/timer.h" 140 | #include "test/thd.h" 141 | #define MEXP 19937 142 | #include "test/SFMT.h" 143 | -------------------------------------------------------------------------------- /test/include/test/jemalloc_test_defs.h.in: -------------------------------------------------------------------------------- 1 | #include "jemalloc/internal/jemalloc_internal_defs.h" 2 | 3 | /* For use by SFMT. */ 4 | #undef HAVE_SSE2 5 | #undef HAVE_ALTIVEC 6 | -------------------------------------------------------------------------------- /test/include/test/mq.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple templated message queue implementation that relies on only mutexes for 3 | * synchronization (which reduces portability issues). Given the following 4 | * setup: 5 | * 6 | * typedef struct mq_msg_s mq_msg_t; 7 | * struct mq_msg_s { 8 | * mq_msg(mq_msg_t) link; 9 | * [message data] 10 | * }; 11 | * mq_gen(, mq_, mq_t, mq_msg_t, link) 12 | * 13 | * The API is as follows: 14 | * 15 | * bool mq_init(mq_t *mq); 16 | * void mq_fini(mq_t *mq); 17 | * unsigned mq_count(mq_t *mq); 18 | * mq_msg_t *mq_tryget(mq_t *mq); 19 | * mq_msg_t *mq_get(mq_t *mq); 20 | * void mq_put(mq_t *mq, mq_msg_t *msg); 21 | * 22 | * The message queue linkage embedded in each message is to be treated as 23 | * externally opaque (no need to initialize or clean up externally). mq_fini() 24 | * does not perform any cleanup of messages, since it knows nothing of their 25 | * payloads. 26 | */ 27 | #define mq_msg(a_mq_msg_type) ql_elm(a_mq_msg_type) 28 | 29 | #define mq_gen(a_attr, a_prefix, a_mq_type, a_mq_msg_type, a_field) \ 30 | typedef struct { \ 31 | mtx_t lock; \ 32 | ql_head(a_mq_msg_type) msgs; \ 33 | unsigned count; \ 34 | } a_mq_type; \ 35 | a_attr bool \ 36 | a_prefix##init(a_mq_type *mq) { \ 37 | \ 38 | if (mtx_init(&mq->lock)) \ 39 | return (true); \ 40 | ql_new(&mq->msgs); \ 41 | mq->count = 0; \ 42 | return (false); \ 43 | } \ 44 | a_attr void \ 45 | a_prefix##fini(a_mq_type *mq) \ 46 | { \ 47 | \ 48 | mtx_fini(&mq->lock); \ 49 | } \ 50 | a_attr unsigned \ 51 | a_prefix##count(a_mq_type *mq) \ 52 | { \ 53 | unsigned count; \ 54 | \ 55 | mtx_lock(&mq->lock); \ 56 | count = mq->count; \ 57 | mtx_unlock(&mq->lock); \ 58 | return (count); \ 59 | } \ 60 | a_attr a_mq_msg_type * \ 61 | a_prefix##tryget(a_mq_type *mq) \ 62 | { \ 63 | a_mq_msg_type *msg; \ 64 | \ 65 | mtx_lock(&mq->lock); \ 66 | msg = ql_first(&mq->msgs); \ 67 | if (msg != NULL) { \ 68 | ql_head_remove(&mq->msgs, a_mq_msg_type, a_field); \ 69 | mq->count--; \ 70 | } \ 71 | mtx_unlock(&mq->lock); \ 72 | return (msg); \ 73 | } \ 74 | a_attr a_mq_msg_type * \ 75 | a_prefix##get(a_mq_type *mq) \ 76 | { \ 77 | a_mq_msg_type *msg; \ 78 | struct timespec timeout; \ 79 | \ 80 | msg = a_prefix##tryget(mq); \ 81 | if (msg != NULL) \ 82 | return (msg); \ 83 | \ 84 | timeout.tv_sec = 0; \ 85 | timeout.tv_nsec = 1; \ 86 | while (true) { \ 87 | nanosleep(&timeout, NULL); \ 88 | msg = a_prefix##tryget(mq); \ 89 | if (msg != NULL) \ 90 | return (msg); \ 91 | if (timeout.tv_sec == 0) { \ 92 | /* Double sleep time, up to max 1 second. */ \ 93 | timeout.tv_nsec <<= 1; \ 94 | if (timeout.tv_nsec >= 1000*1000*1000) { \ 95 | timeout.tv_sec = 1; \ 96 | timeout.tv_nsec = 0; \ 97 | } \ 98 | } \ 99 | } \ 100 | } \ 101 | a_attr void \ 102 | a_prefix##put(a_mq_type *mq, a_mq_msg_type *msg) \ 103 | { \ 104 | \ 105 | mtx_lock(&mq->lock); \ 106 | ql_elm_new(msg, a_field); \ 107 | ql_tail_insert(&mq->msgs, msg, a_field); \ 108 | mq->count++; \ 109 | mtx_unlock(&mq->lock); \ 110 | } 111 | -------------------------------------------------------------------------------- /test/include/test/mtx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * mtx is a slightly simplified version of malloc_mutex. This code duplication 3 | * is unfortunate, but there are allocator bootstrapping considerations that 4 | * would leak into the test infrastructure if malloc_mutex were used directly 5 | * in tests. 6 | */ 7 | 8 | typedef struct { 9 | #ifdef _WIN32 10 | CRITICAL_SECTION lock; 11 | #elif (defined(JEMALLOC_OSSPIN)) 12 | OSSpinLock lock; 13 | #else 14 | pthread_mutex_t lock; 15 | #endif 16 | } mtx_t; 17 | 18 | bool mtx_init(mtx_t *mtx); 19 | void mtx_fini(mtx_t *mtx); 20 | void mtx_lock(mtx_t *mtx); 21 | void mtx_unlock(mtx_t *mtx); 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/include/test/timer.h: -------------------------------------------------------------------------------- 1 | /* Simple timer, for use in benchmark reporting. */ 2 | 3 | #include 4 | 5 | typedef struct { 6 | struct timeval tv0; 7 | struct timeval tv1; 8 | } timedelta_t; 9 | 10 | void timer_start(timedelta_t *timer); 11 | void timer_stop(timedelta_t *timer); 12 | uint64_t timer_usec(const timedelta_t *timer); 13 | void timer_ratio(timedelta_t *a, timedelta_t *b, char *buf, size_t buflen); 14 | -------------------------------------------------------------------------------- /test/integration/ALLOCM_ARENA.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define NTHREADS 10 4 | 5 | void * 6 | thd_start(void *arg) 7 | { 8 | unsigned thread_ind = (unsigned)(uintptr_t)arg; 9 | unsigned arena_ind; 10 | void *p; 11 | size_t rsz, sz; 12 | 13 | sz = sizeof(arena_ind); 14 | assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0, 15 | "Error in arenas.extend"); 16 | 17 | if (thread_ind % 4 != 3) { 18 | size_t mib[3]; 19 | size_t miblen = sizeof(mib) / sizeof(size_t); 20 | const char *dss_precs[] = {"disabled", "primary", "secondary"}; 21 | const char *dss = dss_precs[thread_ind % 22 | (sizeof(dss_precs)/sizeof(char*))]; 23 | assert_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0, 24 | "Error in mallctlnametomib()"); 25 | mib[1] = arena_ind; 26 | assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&dss, 27 | sizeof(const char *)), 0, "Error in mallctlbymib()"); 28 | } 29 | 30 | assert_d_eq(allocm(&p, &rsz, 1, ALLOCM_ARENA(arena_ind)), 31 | ALLOCM_SUCCESS, "Unexpected allocm() error"); 32 | dallocm(p, 0); 33 | 34 | return (NULL); 35 | } 36 | 37 | TEST_BEGIN(test_ALLOCM_ARENA) 38 | { 39 | thd_t thds[NTHREADS]; 40 | unsigned i; 41 | 42 | for (i = 0; i < NTHREADS; i++) { 43 | thd_create(&thds[i], thd_start, 44 | (void *)(uintptr_t)i); 45 | } 46 | 47 | for (i = 0; i < NTHREADS; i++) 48 | thd_join(thds[i], NULL); 49 | } 50 | TEST_END 51 | 52 | int 53 | main(void) 54 | { 55 | 56 | return (test( 57 | test_ALLOCM_ARENA)); 58 | } 59 | -------------------------------------------------------------------------------- /test/integration/aligned_alloc.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define CHUNK 0x400000 4 | /* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */ 5 | #define MAXALIGN ((size_t)0x2000000LU) 6 | #define NITER 4 7 | 8 | TEST_BEGIN(test_alignment_errors) 9 | { 10 | size_t alignment; 11 | void *p; 12 | 13 | alignment = 0; 14 | set_errno(0); 15 | p = aligned_alloc(alignment, 1); 16 | assert_false(p != NULL || get_errno() != EINVAL, 17 | "Expected error for invalid alignment %zu", alignment); 18 | 19 | for (alignment = sizeof(size_t); alignment < MAXALIGN; 20 | alignment <<= 1) { 21 | set_errno(0); 22 | p = aligned_alloc(alignment + 1, 1); 23 | assert_false(p != NULL || get_errno() != EINVAL, 24 | "Expected error for invalid alignment %zu", 25 | alignment + 1); 26 | } 27 | } 28 | TEST_END 29 | 30 | TEST_BEGIN(test_oom_errors) 31 | { 32 | size_t alignment, size; 33 | void *p; 34 | 35 | #if LG_SIZEOF_PTR == 3 36 | alignment = UINT64_C(0x8000000000000000); 37 | size = UINT64_C(0x8000000000000000); 38 | #else 39 | alignment = 0x80000000LU; 40 | size = 0x80000000LU; 41 | #endif 42 | set_errno(0); 43 | p = aligned_alloc(alignment, size); 44 | assert_false(p != NULL || get_errno() != ENOMEM, 45 | "Expected error for aligned_alloc(%zu, %zu)", 46 | alignment, size); 47 | 48 | #if LG_SIZEOF_PTR == 3 49 | alignment = UINT64_C(0x4000000000000000); 50 | size = UINT64_C(0xc000000000000001); 51 | #else 52 | alignment = 0x40000000LU; 53 | size = 0xc0000001LU; 54 | #endif 55 | set_errno(0); 56 | p = aligned_alloc(alignment, size); 57 | assert_false(p != NULL || get_errno() != ENOMEM, 58 | "Expected error for aligned_alloc(%zu, %zu)", 59 | alignment, size); 60 | 61 | alignment = 0x10LU; 62 | #if LG_SIZEOF_PTR == 3 63 | size = UINT64_C(0xfffffffffffffff0); 64 | #else 65 | size = 0xfffffff0LU; 66 | #endif 67 | set_errno(0); 68 | p = aligned_alloc(alignment, size); 69 | assert_false(p != NULL || get_errno() != ENOMEM, 70 | "Expected error for aligned_alloc(&p, %zu, %zu)", 71 | alignment, size); 72 | } 73 | TEST_END 74 | 75 | TEST_BEGIN(test_alignment_and_size) 76 | { 77 | size_t alignment, size, total; 78 | unsigned i; 79 | void *ps[NITER]; 80 | 81 | for (i = 0; i < NITER; i++) 82 | ps[i] = NULL; 83 | 84 | for (alignment = 8; 85 | alignment <= MAXALIGN; 86 | alignment <<= 1) { 87 | total = 0; 88 | for (size = 1; 89 | size < 3 * alignment && size < (1U << 31); 90 | size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { 91 | for (i = 0; i < NITER; i++) { 92 | ps[i] = aligned_alloc(alignment, size); 93 | if (ps[i] == NULL) { 94 | char buf[BUFERROR_BUF]; 95 | 96 | buferror(get_errno(), buf, sizeof(buf)); 97 | test_fail( 98 | "Error for alignment=%zu, " 99 | "size=%zu (%#zx): %s", 100 | alignment, size, size, buf); 101 | } 102 | total += malloc_usable_size(ps[i]); 103 | if (total >= (MAXALIGN << 1)) 104 | break; 105 | } 106 | for (i = 0; i < NITER; i++) { 107 | if (ps[i] != NULL) { 108 | free(ps[i]); 109 | ps[i] = NULL; 110 | } 111 | } 112 | } 113 | } 114 | } 115 | TEST_END 116 | 117 | int 118 | main(void) 119 | { 120 | 121 | return (test( 122 | test_alignment_errors, 123 | test_oom_errors, 124 | test_alignment_and_size)); 125 | } 126 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/integration/allocm.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define CHUNK 0x400000 4 | /* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */ 5 | #define MAXALIGN ((size_t)0x2000000LU) 6 | #define NITER 4 7 | 8 | TEST_BEGIN(test_basic) 9 | { 10 | size_t nsz, rsz, sz; 11 | void *p; 12 | 13 | sz = 42; 14 | nsz = 0; 15 | assert_d_eq(nallocm(&nsz, sz, 0), ALLOCM_SUCCESS, 16 | "Unexpected nallocm() error"); 17 | rsz = 0; 18 | assert_d_eq(allocm(&p, &rsz, sz, 0), ALLOCM_SUCCESS, 19 | "Unexpected allocm() error"); 20 | assert_zu_ge(rsz, sz, "Real size smaller than expected"); 21 | assert_zu_eq(nsz, rsz, "nallocm()/allocm() rsize mismatch"); 22 | assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS, 23 | "Unexpected dallocm() error"); 24 | 25 | assert_d_eq(allocm(&p, NULL, sz, 0), ALLOCM_SUCCESS, 26 | "Unexpected allocm() error"); 27 | assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS, 28 | "Unexpected dallocm() error"); 29 | 30 | nsz = 0; 31 | assert_d_eq(nallocm(&nsz, sz, ALLOCM_ZERO), ALLOCM_SUCCESS, 32 | "Unexpected nallocm() error"); 33 | rsz = 0; 34 | assert_d_eq(allocm(&p, &rsz, sz, ALLOCM_ZERO), ALLOCM_SUCCESS, 35 | "Unexpected allocm() error"); 36 | assert_zu_eq(nsz, rsz, "nallocm()/allocm() rsize mismatch"); 37 | assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS, 38 | "Unexpected dallocm() error"); 39 | } 40 | TEST_END 41 | 42 | TEST_BEGIN(test_alignment_and_size) 43 | { 44 | int r; 45 | size_t nsz, rsz, sz, alignment, total; 46 | unsigned i; 47 | void *ps[NITER]; 48 | 49 | for (i = 0; i < NITER; i++) 50 | ps[i] = NULL; 51 | 52 | for (alignment = 8; 53 | alignment <= MAXALIGN; 54 | alignment <<= 1) { 55 | total = 0; 56 | for (sz = 1; 57 | sz < 3 * alignment && sz < (1U << 31); 58 | sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { 59 | for (i = 0; i < NITER; i++) { 60 | nsz = 0; 61 | r = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment) | 62 | ALLOCM_ZERO); 63 | assert_d_eq(r, ALLOCM_SUCCESS, 64 | "nallocm() error for alignment=%zu, " 65 | "size=%zu (%#zx): %d", 66 | alignment, sz, sz, r); 67 | rsz = 0; 68 | r = allocm(&ps[i], &rsz, sz, 69 | ALLOCM_ALIGN(alignment) | ALLOCM_ZERO); 70 | assert_d_eq(r, ALLOCM_SUCCESS, 71 | "allocm() error for alignment=%zu, " 72 | "size=%zu (%#zx): %d", 73 | alignment, sz, sz, r); 74 | assert_zu_ge(rsz, sz, 75 | "Real size smaller than expected for " 76 | "alignment=%zu, size=%zu", alignment, sz); 77 | assert_zu_eq(nsz, rsz, 78 | "nallocm()/allocm() rsize mismatch for " 79 | "alignment=%zu, size=%zu", alignment, sz); 80 | assert_ptr_null( 81 | (void *)((uintptr_t)ps[i] & (alignment-1)), 82 | "%p inadequately aligned for" 83 | " alignment=%zu, size=%zu", ps[i], 84 | alignment, sz); 85 | sallocm(ps[i], &rsz, 0); 86 | total += rsz; 87 | if (total >= (MAXALIGN << 1)) 88 | break; 89 | } 90 | for (i = 0; i < NITER; i++) { 91 | if (ps[i] != NULL) { 92 | dallocm(ps[i], 0); 93 | ps[i] = NULL; 94 | } 95 | } 96 | } 97 | } 98 | } 99 | TEST_END 100 | 101 | int 102 | main(void) 103 | { 104 | 105 | return (test( 106 | test_basic, 107 | test_alignment_and_size)); 108 | } 109 | -------------------------------------------------------------------------------- /test/integration/mallocx.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define CHUNK 0x400000 4 | /* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */ 5 | #define MAXALIGN ((size_t)0x2000000LU) 6 | #define NITER 4 7 | 8 | TEST_BEGIN(test_basic) 9 | { 10 | size_t nsz, rsz, sz; 11 | void *p; 12 | 13 | sz = 42; 14 | nsz = nallocx(sz, 0); 15 | assert_zu_ne(nsz, 0, "Unexpected nallocx() error"); 16 | p = mallocx(sz, 0); 17 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 18 | rsz = sallocx(p, 0); 19 | assert_zu_ge(rsz, sz, "Real size smaller than expected"); 20 | assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch"); 21 | dallocx(p, 0); 22 | 23 | p = mallocx(sz, 0); 24 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 25 | dallocx(p, 0); 26 | 27 | nsz = nallocx(sz, MALLOCX_ZERO); 28 | assert_zu_ne(nsz, 0, "Unexpected nallocx() error"); 29 | p = mallocx(sz, MALLOCX_ZERO); 30 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 31 | rsz = sallocx(p, 0); 32 | assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch"); 33 | dallocx(p, 0); 34 | } 35 | TEST_END 36 | 37 | TEST_BEGIN(test_alignment_and_size) 38 | { 39 | size_t nsz, rsz, sz, alignment, total; 40 | unsigned i; 41 | void *ps[NITER]; 42 | 43 | for (i = 0; i < NITER; i++) 44 | ps[i] = NULL; 45 | 46 | for (alignment = 8; 47 | alignment <= MAXALIGN; 48 | alignment <<= 1) { 49 | total = 0; 50 | for (sz = 1; 51 | sz < 3 * alignment && sz < (1U << 31); 52 | sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { 53 | for (i = 0; i < NITER; i++) { 54 | nsz = nallocx(sz, MALLOCX_ALIGN(alignment) | 55 | MALLOCX_ZERO); 56 | assert_zu_ne(nsz, 0, 57 | "nallocx() error for alignment=%zu, " 58 | "size=%zu (%#zx)", alignment, sz, sz); 59 | ps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) | 60 | MALLOCX_ZERO); 61 | assert_ptr_not_null(ps[i], 62 | "mallocx() error for alignment=%zu, " 63 | "size=%zu (%#zx)", alignment, sz, sz); 64 | rsz = sallocx(ps[i], 0); 65 | assert_zu_ge(rsz, sz, 66 | "Real size smaller than expected for " 67 | "alignment=%zu, size=%zu", alignment, sz); 68 | assert_zu_eq(nsz, rsz, 69 | "nallocx()/sallocx() size mismatch for " 70 | "alignment=%zu, size=%zu", alignment, sz); 71 | assert_ptr_null( 72 | (void *)((uintptr_t)ps[i] & (alignment-1)), 73 | "%p inadequately aligned for" 74 | " alignment=%zu, size=%zu", ps[i], 75 | alignment, sz); 76 | total += rsz; 77 | if (total >= (MAXALIGN << 1)) 78 | break; 79 | } 80 | for (i = 0; i < NITER; i++) { 81 | if (ps[i] != NULL) { 82 | dallocx(ps[i], 0); 83 | ps[i] = NULL; 84 | } 85 | } 86 | } 87 | } 88 | } 89 | TEST_END 90 | 91 | int 92 | main(void) 93 | { 94 | 95 | return (test( 96 | test_basic, 97 | test_alignment_and_size)); 98 | } 99 | -------------------------------------------------------------------------------- /test/integration/mremap.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | TEST_BEGIN(test_mremap) 4 | { 5 | int err; 6 | size_t sz, lg_chunk, chunksize, i; 7 | char *p, *q; 8 | 9 | sz = sizeof(lg_chunk); 10 | err = mallctl("opt.lg_chunk", &lg_chunk, &sz, NULL, 0); 11 | assert_d_eq(err, 0, "Error in mallctl(): %s", strerror(err)); 12 | chunksize = ((size_t)1U) << lg_chunk; 13 | 14 | p = (char *)malloc(chunksize); 15 | assert_ptr_not_null(p, "malloc(%zu) --> %p", chunksize, p); 16 | memset(p, 'a', chunksize); 17 | 18 | q = (char *)realloc(p, chunksize * 2); 19 | assert_ptr_not_null(q, "realloc(%p, %zu) --> %p", p, chunksize * 2, 20 | q); 21 | for (i = 0; i < chunksize; i++) { 22 | assert_c_eq(q[i], 'a', 23 | "realloc() should preserve existing bytes across copies"); 24 | } 25 | 26 | p = q; 27 | 28 | q = (char *)realloc(p, chunksize); 29 | assert_ptr_not_null(q, "realloc(%p, %zu) --> %p", p, chunksize, q); 30 | for (i = 0; i < chunksize; i++) { 31 | assert_c_eq(q[i], 'a', 32 | "realloc() should preserve existing bytes across copies"); 33 | } 34 | 35 | free(q); 36 | } 37 | TEST_END 38 | 39 | int 40 | main(void) 41 | { 42 | 43 | return (test( 44 | test_mremap)); 45 | } 46 | -------------------------------------------------------------------------------- /test/integration/posix_memalign.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #define CHUNK 0x400000 4 | /* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */ 5 | #define MAXALIGN ((size_t)0x2000000LU) 6 | #define NITER 4 7 | 8 | TEST_BEGIN(test_alignment_errors) 9 | { 10 | size_t alignment; 11 | void *p; 12 | 13 | for (alignment = 0; alignment < sizeof(void *); alignment++) { 14 | assert_d_eq(posix_memalign(&p, alignment, 1), EINVAL, 15 | "Expected error for invalid alignment %zu", 16 | alignment); 17 | } 18 | 19 | for (alignment = sizeof(size_t); alignment < MAXALIGN; 20 | alignment <<= 1) { 21 | assert_d_ne(posix_memalign(&p, alignment + 1, 1), 0, 22 | "Expected error for invalid alignment %zu", 23 | alignment + 1); 24 | } 25 | } 26 | TEST_END 27 | 28 | TEST_BEGIN(test_oom_errors) 29 | { 30 | size_t alignment, size; 31 | void *p; 32 | 33 | #if LG_SIZEOF_PTR == 3 34 | alignment = UINT64_C(0x8000000000000000); 35 | size = UINT64_C(0x8000000000000000); 36 | #else 37 | alignment = 0x80000000LU; 38 | size = 0x80000000LU; 39 | #endif 40 | assert_d_ne(posix_memalign(&p, alignment, size), 0, 41 | "Expected error for posix_memalign(&p, %zu, %zu)", 42 | alignment, size); 43 | 44 | #if LG_SIZEOF_PTR == 3 45 | alignment = UINT64_C(0x4000000000000000); 46 | size = UINT64_C(0xc000000000000001); 47 | #else 48 | alignment = 0x40000000LU; 49 | size = 0xc0000001LU; 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 | alignment = 0x10LU; 56 | #if LG_SIZEOF_PTR == 3 57 | size = UINT64_C(0xfffffffffffffff0); 58 | #else 59 | size = 0xfffffff0LU; 60 | #endif 61 | assert_d_ne(posix_memalign(&p, alignment, size), 0, 62 | "Expected error for posix_memalign(&p, %zu, %zu)", 63 | alignment, size); 64 | } 65 | TEST_END 66 | 67 | TEST_BEGIN(test_alignment_and_size) 68 | { 69 | size_t alignment, size, total; 70 | unsigned i; 71 | int err; 72 | void *ps[NITER]; 73 | 74 | for (i = 0; i < NITER; i++) 75 | ps[i] = NULL; 76 | 77 | for (alignment = 8; 78 | alignment <= MAXALIGN; 79 | alignment <<= 1) { 80 | total = 0; 81 | for (size = 1; 82 | size < 3 * alignment && size < (1U << 31); 83 | size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { 84 | for (i = 0; i < NITER; i++) { 85 | err = posix_memalign(&ps[i], 86 | alignment, size); 87 | if (err) { 88 | char buf[BUFERROR_BUF]; 89 | 90 | buferror(get_errno(), buf, sizeof(buf)); 91 | test_fail( 92 | "Error for alignment=%zu, " 93 | "size=%zu (%#zx): %s", 94 | alignment, size, size, buf); 95 | } 96 | total += malloc_usable_size(ps[i]); 97 | if (total >= (MAXALIGN << 1)) 98 | break; 99 | } 100 | for (i = 0; i < NITER; i++) { 101 | if (ps[i] != NULL) { 102 | free(ps[i]); 103 | ps[i] = NULL; 104 | } 105 | } 106 | } 107 | } 108 | } 109 | TEST_END 110 | 111 | int 112 | main(void) 113 | { 114 | 115 | return (test( 116 | test_alignment_errors, 117 | test_oom_errors, 118 | test_alignment_and_size)); 119 | } 120 | -------------------------------------------------------------------------------- /test/integration/rallocm.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | TEST_BEGIN(test_same_size) 4 | { 5 | void *p, *q; 6 | size_t sz, tsz; 7 | 8 | assert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS, 9 | "Unexpected allocm() error"); 10 | 11 | q = p; 12 | assert_d_eq(rallocm(&q, &tsz, sz, 0, ALLOCM_NO_MOVE), ALLOCM_SUCCESS, 13 | "Unexpected rallocm() error"); 14 | assert_ptr_eq(q, p, "Unexpected object move"); 15 | assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz); 16 | 17 | assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS, 18 | "Unexpected dallocm() error"); 19 | } 20 | TEST_END 21 | 22 | TEST_BEGIN(test_extra_no_move) 23 | { 24 | void *p, *q; 25 | size_t sz, tsz; 26 | 27 | assert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS, 28 | "Unexpected allocm() error"); 29 | 30 | q = p; 31 | assert_d_eq(rallocm(&q, &tsz, sz, sz-42, ALLOCM_NO_MOVE), 32 | ALLOCM_SUCCESS, "Unexpected rallocm() error"); 33 | assert_ptr_eq(q, p, "Unexpected object move"); 34 | assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz); 35 | 36 | assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS, 37 | "Unexpected dallocm() error"); 38 | } 39 | TEST_END 40 | 41 | TEST_BEGIN(test_no_move_fail) 42 | { 43 | void *p, *q; 44 | size_t sz, tsz; 45 | 46 | assert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS, 47 | "Unexpected allocm() error"); 48 | 49 | q = p; 50 | assert_d_eq(rallocm(&q, &tsz, sz + 5, 0, ALLOCM_NO_MOVE), 51 | ALLOCM_ERR_NOT_MOVED, "Unexpected rallocm() result"); 52 | assert_ptr_eq(q, p, "Unexpected object move"); 53 | assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz); 54 | 55 | assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS, 56 | "Unexpected dallocm() error"); 57 | } 58 | TEST_END 59 | 60 | TEST_BEGIN(test_grow_and_shrink) 61 | { 62 | void *p, *q; 63 | size_t tsz; 64 | #define NCYCLES 3 65 | unsigned i, j; 66 | #define NSZS 2500 67 | size_t szs[NSZS]; 68 | #define MAXSZ ZU(12 * 1024 * 1024) 69 | 70 | assert_d_eq(allocm(&p, &szs[0], 1, 0), ALLOCM_SUCCESS, 71 | "Unexpected allocm() error"); 72 | 73 | for (i = 0; i < NCYCLES; i++) { 74 | for (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) { 75 | q = p; 76 | assert_d_eq(rallocm(&q, &szs[j], szs[j-1]+1, 0, 0), 77 | ALLOCM_SUCCESS, 78 | "Unexpected rallocm() error for size=%zu-->%zu", 79 | szs[j-1], szs[j-1]+1); 80 | assert_zu_ne(szs[j], szs[j-1]+1, 81 | "Expected size to at least: %zu", szs[j-1]+1); 82 | p = q; 83 | } 84 | 85 | for (j--; j > 0; j--) { 86 | q = p; 87 | assert_d_eq(rallocm(&q, &tsz, szs[j-1], 0, 0), 88 | ALLOCM_SUCCESS, 89 | "Unexpected rallocm() error for size=%zu-->%zu", 90 | szs[j], szs[j-1]); 91 | assert_zu_eq(tsz, szs[j-1], 92 | "Expected size=%zu, got size=%zu", szs[j-1], tsz); 93 | p = q; 94 | } 95 | } 96 | 97 | assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS, 98 | "Unexpected dallocm() error"); 99 | } 100 | TEST_END 101 | 102 | int 103 | main(void) 104 | { 105 | 106 | return (test( 107 | test_same_size, 108 | test_extra_no_move, 109 | test_no_move_fail, 110 | test_grow_and_shrink)); 111 | } 112 | -------------------------------------------------------------------------------- /test/integration/rallocx.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | TEST_BEGIN(test_grow_and_shrink) 4 | { 5 | void *p, *q; 6 | size_t tsz; 7 | #define NCYCLES 3 8 | unsigned i, j; 9 | #define NSZS 2500 10 | size_t szs[NSZS]; 11 | #define MAXSZ ZU(12 * 1024 * 1024) 12 | 13 | p = mallocx(1, 0); 14 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 15 | szs[0] = sallocx(p, 0); 16 | 17 | for (i = 0; i < NCYCLES; i++) { 18 | for (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) { 19 | q = rallocx(p, szs[j-1]+1, 0); 20 | assert_ptr_not_null(q, 21 | "Unexpected rallocx() error for size=%zu-->%zu", 22 | szs[j-1], szs[j-1]+1); 23 | szs[j] = sallocx(q, 0); 24 | assert_zu_ne(szs[j], szs[j-1]+1, 25 | "Expected size to at least: %zu", szs[j-1]+1); 26 | p = q; 27 | } 28 | 29 | for (j--; j > 0; j--) { 30 | q = rallocx(p, szs[j-1], 0); 31 | assert_ptr_not_null(q, 32 | "Unexpected rallocx() error for size=%zu-->%zu", 33 | szs[j], szs[j-1]); 34 | tsz = sallocx(q, 0); 35 | assert_zu_eq(tsz, szs[j-1], 36 | "Expected size=%zu, got size=%zu", szs[j-1], tsz); 37 | p = q; 38 | } 39 | } 40 | 41 | dallocx(p, 0); 42 | #undef MAXSZ 43 | #undef NSZS 44 | #undef NCYCLES 45 | } 46 | TEST_END 47 | 48 | static bool 49 | validate_fill(const void *p, uint8_t c, size_t offset, size_t len) 50 | { 51 | bool ret = false; 52 | const uint8_t *buf = (const uint8_t *)p; 53 | size_t i; 54 | 55 | for (i = 0; i < len; i++) { 56 | uint8_t b = buf[offset+i]; 57 | if (b != c) { 58 | test_fail("Allocation at %p contains %#x rather than " 59 | "%#x at offset %zu", p, b, c, offset+i); 60 | ret = true; 61 | } 62 | } 63 | 64 | return (ret); 65 | } 66 | 67 | TEST_BEGIN(test_zero) 68 | { 69 | void *p, *q; 70 | size_t psz, qsz, i, j; 71 | size_t start_sizes[] = {1, 3*1024, 63*1024, 4095*1024}; 72 | #define FILL_BYTE 0xaaU 73 | #define RANGE 2048 74 | 75 | for (i = 0; i < sizeof(start_sizes)/sizeof(size_t); i++) { 76 | size_t start_size = start_sizes[i]; 77 | p = mallocx(start_size, MALLOCX_ZERO); 78 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 79 | psz = sallocx(p, 0); 80 | 81 | assert_false(validate_fill(p, 0, 0, psz), 82 | "Expected zeroed memory"); 83 | memset(p, FILL_BYTE, psz); 84 | assert_false(validate_fill(p, FILL_BYTE, 0, psz), 85 | "Expected filled memory"); 86 | 87 | for (j = 1; j < RANGE; j++) { 88 | q = rallocx(p, start_size+j, MALLOCX_ZERO); 89 | assert_ptr_not_null(q, "Unexpected rallocx() error"); 90 | qsz = sallocx(q, 0); 91 | if (q != p || qsz != psz) { 92 | assert_false(validate_fill(q, FILL_BYTE, 0, 93 | psz), "Expected filled memory"); 94 | assert_false(validate_fill(q, 0, psz, qsz-psz), 95 | "Expected zeroed memory"); 96 | } 97 | if (psz != qsz) { 98 | memset(q+psz, FILL_BYTE, qsz-psz); 99 | psz = qsz; 100 | } 101 | p = q; 102 | } 103 | assert_false(validate_fill(p, FILL_BYTE, 0, psz), 104 | "Expected filled memory"); 105 | dallocx(p, 0); 106 | } 107 | #undef FILL_BYTE 108 | } 109 | TEST_END 110 | 111 | TEST_BEGIN(test_align) 112 | { 113 | void *p, *q; 114 | size_t align; 115 | #define MAX_ALIGN (ZU(1) << 29) 116 | 117 | align = ZU(1); 118 | p = mallocx(1, MALLOCX_ALIGN(align)); 119 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 120 | 121 | for (align <<= 1; align <= MAX_ALIGN; align <<= 1) { 122 | q = rallocx(p, 1, MALLOCX_ALIGN(align)); 123 | assert_ptr_not_null(q, 124 | "Unexpected rallocx() error for align=%zu", align); 125 | assert_ptr_null( 126 | (void *)((uintptr_t)q & (align-1)), 127 | "%p inadequately aligned for align=%zu", 128 | q, align); 129 | p = q; 130 | } 131 | dallocx(p, 0); 132 | #undef MAX_ALIGN 133 | } 134 | TEST_END 135 | 136 | TEST_BEGIN(test_lg_align_and_zero) 137 | { 138 | void *p, *q; 139 | size_t lg_align, sz; 140 | #define MAX_LG_ALIGN 29 141 | #define MAX_VALIDATE (ZU(1) << 22) 142 | 143 | lg_align = ZU(0); 144 | p = mallocx(1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO); 145 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 146 | 147 | for (lg_align++; lg_align <= MAX_LG_ALIGN; lg_align++) { 148 | q = rallocx(p, 1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO); 149 | assert_ptr_not_null(q, 150 | "Unexpected rallocx() error for lg_align=%zu", lg_align); 151 | assert_ptr_null( 152 | (void *)((uintptr_t)q & ((ZU(1) << lg_align)-1)), 153 | "%p inadequately aligned for lg_align=%zu", 154 | q, lg_align); 155 | sz = sallocx(q, 0); 156 | if ((sz << 1) <= MAX_VALIDATE) { 157 | assert_false(validate_fill(q, 0, 0, sz), 158 | "Expected zeroed memory"); 159 | } else { 160 | assert_false(validate_fill(q, 0, 0, MAX_VALIDATE), 161 | "Expected zeroed memory"); 162 | assert_false(validate_fill(q+sz-MAX_VALIDATE, 0, 0, 163 | MAX_VALIDATE), "Expected zeroed memory"); 164 | } 165 | p = q; 166 | } 167 | dallocx(p, 0); 168 | #undef MAX_VALIDATE 169 | #undef MAX_LG_ALIGN 170 | } 171 | TEST_END 172 | 173 | int 174 | main(void) 175 | { 176 | 177 | return (test( 178 | test_grow_and_shrink, 179 | test_zero, 180 | test_align, 181 | test_lg_align_and_zero)); 182 | } 183 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/integration/xallocx.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | TEST_BEGIN(test_same_size) 4 | { 5 | void *p; 6 | size_t sz, tsz; 7 | 8 | p = mallocx(42, 0); 9 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 10 | sz = sallocx(p, 0); 11 | 12 | tsz = xallocx(p, sz, 0, 0); 13 | assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz); 14 | 15 | dallocx(p, 0); 16 | } 17 | TEST_END 18 | 19 | TEST_BEGIN(test_extra_no_move) 20 | { 21 | void *p; 22 | size_t sz, tsz; 23 | 24 | p = mallocx(42, 0); 25 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 26 | sz = sallocx(p, 0); 27 | 28 | tsz = xallocx(p, sz, sz-42, 0); 29 | assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz); 30 | 31 | dallocx(p, 0); 32 | } 33 | TEST_END 34 | 35 | TEST_BEGIN(test_no_move_fail) 36 | { 37 | void *p; 38 | size_t sz, tsz; 39 | 40 | p = mallocx(42, 0); 41 | assert_ptr_not_null(p, "Unexpected mallocx() error"); 42 | sz = sallocx(p, 0); 43 | 44 | tsz = xallocx(p, sz + 5, 0, 0); 45 | assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz); 46 | 47 | dallocx(p, 0); 48 | } 49 | TEST_END 50 | 51 | int 52 | main(void) 53 | { 54 | 55 | return (test( 56 | test_same_size, 57 | test_extra_no_move, 58 | test_no_move_fail)); 59 | } 60 | -------------------------------------------------------------------------------- /test/src/math.c: -------------------------------------------------------------------------------- 1 | #define MATH_C_ 2 | #include "test/jemalloc_test.h" 3 | -------------------------------------------------------------------------------- /test/src/mtx.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | bool 4 | mtx_init(mtx_t *mtx) 5 | { 6 | 7 | #ifdef _WIN32 8 | if (!InitializeCriticalSectionAndSpinCount(&mtx->lock, _CRT_SPINCOUNT)) 9 | return (true); 10 | #elif (defined(JEMALLOC_OSSPIN)) 11 | mtx->lock = 0; 12 | #else 13 | pthread_mutexattr_t attr; 14 | 15 | if (pthread_mutexattr_init(&attr) != 0) 16 | return (true); 17 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT); 18 | if (pthread_mutex_init(&mtx->lock, &attr) != 0) { 19 | pthread_mutexattr_destroy(&attr); 20 | return (true); 21 | } 22 | pthread_mutexattr_destroy(&attr); 23 | #endif 24 | return (false); 25 | } 26 | 27 | void 28 | mtx_fini(mtx_t *mtx) 29 | { 30 | 31 | #ifdef _WIN32 32 | #elif (defined(JEMALLOC_OSSPIN)) 33 | #else 34 | pthread_mutex_destroy(&mtx->lock); 35 | #endif 36 | } 37 | 38 | void 39 | mtx_lock(mtx_t *mtx) 40 | { 41 | 42 | #ifdef _WIN32 43 | EnterCriticalSection(&mtx->lock); 44 | #elif (defined(JEMALLOC_OSSPIN)) 45 | OSSpinLockLock(&mtx->lock); 46 | #else 47 | pthread_mutex_lock(&mtx->lock); 48 | #endif 49 | } 50 | 51 | void 52 | mtx_unlock(mtx_t *mtx) 53 | { 54 | 55 | #ifdef _WIN32 56 | LeaveCriticalSection(&mtx->lock); 57 | #elif (defined(JEMALLOC_OSSPIN)) 58 | OSSpinLockUnlock(&mtx->lock); 59 | #else 60 | pthread_mutex_unlock(&mtx->lock); 61 | #endif 62 | } 63 | -------------------------------------------------------------------------------- /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_ATTR(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_ATTR(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 | test_status_t 64 | p_test(test_t* t, ...) 65 | { 66 | test_status_t ret = test_status_pass; 67 | va_list ap; 68 | 69 | va_start(ap, t); 70 | for (; t != NULL; t = va_arg(ap, test_t*)) { 71 | t(); 72 | if (test_status > ret) 73 | ret = test_status; 74 | } 75 | va_end(ap); 76 | 77 | malloc_printf("--- %s: %u/%u, %s: %u/%u, %s: %u/%u ---\n", 78 | test_status_string(test_status_pass), 79 | test_counts[test_status_pass], test_count, 80 | test_status_string(test_status_skip), 81 | test_counts[test_status_skip], test_count, 82 | test_status_string(test_status_fail), 83 | test_counts[test_status_fail], test_count); 84 | 85 | return (ret); 86 | } 87 | 88 | void 89 | p_test_fail(const char *format, ...) 90 | { 91 | va_list ap; 92 | 93 | va_start(ap, format); 94 | malloc_vcprintf(NULL, NULL, format, ap); 95 | format = va_arg(ap, const char *); 96 | malloc_vcprintf(NULL, NULL, format, ap); 97 | va_end(ap); 98 | malloc_printf("\n"); 99 | test_status = test_status_fail; 100 | } 101 | -------------------------------------------------------------------------------- /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 | WaitForSingleObject(thd, INFINITE); 18 | } 19 | 20 | #else 21 | void 22 | thd_create(thd_t *thd, void *(*proc)(void *), void *arg) 23 | { 24 | 25 | if (pthread_create(thd, NULL, proc, arg) != 0) 26 | test_fail("Error in pthread_create()\n"); 27 | } 28 | 29 | void 30 | thd_join(thd_t thd, void **ret) 31 | { 32 | 33 | pthread_join(thd, ret); 34 | } 35 | #endif 36 | -------------------------------------------------------------------------------- /test/src/timer.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | void 4 | timer_start(timedelta_t *timer) 5 | { 6 | 7 | gettimeofday(&timer->tv0, NULL); 8 | } 9 | 10 | void 11 | timer_stop(timedelta_t *timer) 12 | { 13 | 14 | gettimeofday(&timer->tv1, NULL); 15 | } 16 | 17 | uint64_t 18 | timer_usec(const timedelta_t *timer) 19 | { 20 | 21 | return (((timer->tv1.tv_sec - timer->tv0.tv_sec) * 1000000) + 22 | timer->tv1.tv_usec - timer->tv0.tv_usec); 23 | } 24 | 25 | void 26 | timer_ratio(timedelta_t *a, timedelta_t *b, char *buf, size_t buflen) 27 | { 28 | uint64_t t0 = timer_usec(a); 29 | uint64_t t1 = timer_usec(b); 30 | uint64_t mult; 31 | unsigned i = 0; 32 | unsigned j; 33 | int n; 34 | 35 | /* Whole. */ 36 | n = malloc_snprintf(&buf[i], buflen-i, "%"PRIu64, t0 / t1); 37 | i += n; 38 | if (i >= buflen) 39 | return; 40 | mult = 1; 41 | for (j = 0; j < n; j++) 42 | mult *= 10; 43 | 44 | /* Decimal. */ 45 | n = malloc_snprintf(&buf[i], buflen-i, "."); 46 | i += n; 47 | 48 | /* Fraction. */ 49 | while (i < buflen-1) { 50 | uint64_t round = (i+1 == buflen-1 && ((t0 * mult * 10 / t1) % 10 51 | >= 5)) ? 1 : 0; 52 | n = malloc_snprintf(&buf[i], buflen-i, 53 | "%"PRIu64, (t0 * mult / t1) % 10 + round); 54 | i += n; 55 | mult *= 10; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/unit/bitmap.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | #if (LG_BITMAP_MAXBITS > 12) 4 | # define MAXBITS 4500 5 | #else 6 | # define MAXBITS (1U << LG_BITMAP_MAXBITS) 7 | #endif 8 | 9 | TEST_BEGIN(test_bitmap_size) 10 | { 11 | size_t i, prev_size; 12 | 13 | prev_size = 0; 14 | for (i = 1; i <= MAXBITS; i++) { 15 | size_t size = bitmap_size(i); 16 | assert_true(size >= prev_size, 17 | "Bitmap size is smaller than expected"); 18 | prev_size = size; 19 | } 20 | } 21 | TEST_END 22 | 23 | TEST_BEGIN(test_bitmap_init) 24 | { 25 | size_t i; 26 | 27 | for (i = 1; i <= MAXBITS; i++) { 28 | bitmap_info_t binfo; 29 | bitmap_info_init(&binfo, i); 30 | { 31 | size_t j; 32 | bitmap_t *bitmap = malloc(sizeof(bitmap_t) * 33 | bitmap_info_ngroups(&binfo)); 34 | bitmap_init(bitmap, &binfo); 35 | 36 | for (j = 0; j < i; j++) { 37 | assert_false(bitmap_get(bitmap, &binfo, j), 38 | "Bit should be unset"); 39 | } 40 | free(bitmap); 41 | } 42 | } 43 | } 44 | TEST_END 45 | 46 | TEST_BEGIN(test_bitmap_set) 47 | { 48 | size_t i; 49 | 50 | for (i = 1; i <= MAXBITS; i++) { 51 | bitmap_info_t binfo; 52 | bitmap_info_init(&binfo, i); 53 | { 54 | size_t j; 55 | bitmap_t *bitmap = malloc(sizeof(bitmap_t) * 56 | bitmap_info_ngroups(&binfo)); 57 | bitmap_init(bitmap, &binfo); 58 | 59 | for (j = 0; j < i; j++) 60 | bitmap_set(bitmap, &binfo, j); 61 | assert_true(bitmap_full(bitmap, &binfo), 62 | "All bits should be set"); 63 | free(bitmap); 64 | } 65 | } 66 | } 67 | TEST_END 68 | 69 | TEST_BEGIN(test_bitmap_unset) 70 | { 71 | size_t i; 72 | 73 | for (i = 1; i <= MAXBITS; i++) { 74 | bitmap_info_t binfo; 75 | bitmap_info_init(&binfo, i); 76 | { 77 | size_t j; 78 | bitmap_t *bitmap = malloc(sizeof(bitmap_t) * 79 | bitmap_info_ngroups(&binfo)); 80 | bitmap_init(bitmap, &binfo); 81 | 82 | for (j = 0; j < i; j++) 83 | bitmap_set(bitmap, &binfo, j); 84 | assert_true(bitmap_full(bitmap, &binfo), 85 | "All bits should be set"); 86 | for (j = 0; j < i; j++) 87 | bitmap_unset(bitmap, &binfo, j); 88 | for (j = 0; j < i; j++) 89 | bitmap_set(bitmap, &binfo, j); 90 | assert_true(bitmap_full(bitmap, &binfo), 91 | "All bits should be set"); 92 | free(bitmap); 93 | } 94 | } 95 | } 96 | TEST_END 97 | 98 | TEST_BEGIN(test_bitmap_sfu) 99 | { 100 | size_t i; 101 | 102 | for (i = 1; i <= MAXBITS; i++) { 103 | bitmap_info_t binfo; 104 | bitmap_info_init(&binfo, i); 105 | { 106 | ssize_t j; 107 | bitmap_t *bitmap = malloc(sizeof(bitmap_t) * 108 | bitmap_info_ngroups(&binfo)); 109 | bitmap_init(bitmap, &binfo); 110 | 111 | /* Iteratively set bits starting at the beginning. */ 112 | for (j = 0; j < i; j++) { 113 | assert_zd_eq(bitmap_sfu(bitmap, &binfo), j, 114 | "First unset bit should be just after " 115 | "previous first unset bit"); 116 | } 117 | assert_true(bitmap_full(bitmap, &binfo), 118 | "All bits should be set"); 119 | 120 | /* 121 | * Iteratively unset bits starting at the end, and 122 | * verify that bitmap_sfu() reaches the unset bits. 123 | */ 124 | for (j = i - 1; j >= 0; j--) { 125 | bitmap_unset(bitmap, &binfo, j); 126 | assert_zd_eq(bitmap_sfu(bitmap, &binfo), j, 127 | "First unset bit should the bit previously " 128 | "unset"); 129 | bitmap_unset(bitmap, &binfo, j); 130 | } 131 | assert_false(bitmap_get(bitmap, &binfo, 0), 132 | "Bit should be unset"); 133 | 134 | /* 135 | * Iteratively set bits starting at the beginning, and 136 | * verify that bitmap_sfu() looks past them. 137 | */ 138 | for (j = 1; j < i; j++) { 139 | bitmap_set(bitmap, &binfo, j - 1); 140 | assert_zd_eq(bitmap_sfu(bitmap, &binfo), j, 141 | "First unset bit should be just after the " 142 | "bit previously set"); 143 | bitmap_unset(bitmap, &binfo, j); 144 | } 145 | assert_zd_eq(bitmap_sfu(bitmap, &binfo), i - 1, 146 | "First unset bit should be the last bit"); 147 | assert_true(bitmap_full(bitmap, &binfo), 148 | "All bits should be set"); 149 | free(bitmap); 150 | } 151 | } 152 | } 153 | TEST_END 154 | 155 | int 156 | main(void) 157 | { 158 | 159 | return (test( 160 | test_bitmap_size, 161 | test_bitmap_init, 162 | test_bitmap_set, 163 | test_bitmap_unset, 164 | test_bitmap_sfu)); 165 | } 166 | -------------------------------------------------------------------------------- /test/unit/hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is based on code that is part of SMHasher 3 | * (https://code.google.com/p/smhasher/), and is subject to the MIT license 4 | * (http://www.opensource.org/licenses/mit-license.php). Both email addresses 5 | * associated with the source code's revision history belong to Austin Appleby, 6 | * and the revision history ranges from 2010 to 2012. Therefore the copyright 7 | * and license are here taken to be: 8 | * 9 | * Copyright (c) 2010-2012 Austin Appleby 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | * THE SOFTWARE. 28 | */ 29 | 30 | #include "test/jemalloc_test.h" 31 | 32 | typedef enum { 33 | hash_variant_x86_32, 34 | hash_variant_x86_128, 35 | hash_variant_x64_128 36 | } hash_variant_t; 37 | 38 | static size_t 39 | hash_variant_bits(hash_variant_t variant) 40 | { 41 | 42 | switch (variant) { 43 | case hash_variant_x86_32: return (32); 44 | case hash_variant_x86_128: return (128); 45 | case hash_variant_x64_128: return (128); 46 | default: not_reached(); 47 | } 48 | } 49 | 50 | static const char * 51 | hash_variant_string(hash_variant_t variant) 52 | { 53 | 54 | switch (variant) { 55 | case hash_variant_x86_32: return ("hash_x86_32"); 56 | case hash_variant_x86_128: return ("hash_x86_128"); 57 | case hash_variant_x64_128: return ("hash_x64_128"); 58 | default: not_reached(); 59 | } 60 | } 61 | 62 | static void 63 | hash_variant_verify(hash_variant_t variant) 64 | { 65 | const size_t hashbytes = hash_variant_bits(variant) / 8; 66 | uint8_t key[256]; 67 | uint8_t hashes[hashbytes * 256]; 68 | uint8_t final[hashbytes]; 69 | unsigned i; 70 | uint32_t computed, expected; 71 | 72 | memset(key, 0, sizeof(key)); 73 | memset(hashes, 0, sizeof(hashes)); 74 | memset(final, 0, sizeof(final)); 75 | 76 | /* 77 | * Hash keys of the form {0}, {0,1}, {0,1,2}, ..., {0,1,...,255} as the 78 | * seed. 79 | */ 80 | for (i = 0; i < 256; i++) { 81 | key[i] = (uint8_t)i; 82 | switch (variant) { 83 | case hash_variant_x86_32: { 84 | uint32_t out; 85 | out = hash_x86_32(key, i, 256-i); 86 | memcpy(&hashes[i*hashbytes], &out, hashbytes); 87 | break; 88 | } case hash_variant_x86_128: { 89 | uint64_t out[2]; 90 | hash_x86_128(key, i, 256-i, out); 91 | memcpy(&hashes[i*hashbytes], out, hashbytes); 92 | break; 93 | } case hash_variant_x64_128: { 94 | uint64_t out[2]; 95 | hash_x64_128(key, i, 256-i, out); 96 | memcpy(&hashes[i*hashbytes], out, hashbytes); 97 | break; 98 | } default: not_reached(); 99 | } 100 | } 101 | 102 | /* Hash the result array. */ 103 | switch (variant) { 104 | case hash_variant_x86_32: { 105 | uint32_t out = hash_x86_32(hashes, hashbytes*256, 0); 106 | memcpy(final, &out, sizeof(out)); 107 | break; 108 | } case hash_variant_x86_128: { 109 | uint64_t out[2]; 110 | hash_x86_128(hashes, hashbytes*256, 0, out); 111 | memcpy(final, out, sizeof(out)); 112 | break; 113 | } case hash_variant_x64_128: { 114 | uint64_t out[2]; 115 | hash_x64_128(hashes, hashbytes*256, 0, out); 116 | memcpy(final, out, sizeof(out)); 117 | break; 118 | } default: not_reached(); 119 | } 120 | 121 | computed = (final[0] << 0) | (final[1] << 8) | (final[2] << 16) | 122 | (final[3] << 24); 123 | 124 | switch (variant) { 125 | case hash_variant_x86_32: expected = 0xb0f57ee3U; break; 126 | case hash_variant_x86_128: expected = 0xb3ece62aU; break; 127 | case hash_variant_x64_128: expected = 0x6384ba69U; break; 128 | default: not_reached(); 129 | } 130 | 131 | assert_u32_eq(computed, expected, 132 | "Hash mismatch for %s(): expected %#x but got %#x", 133 | hash_variant_string(variant), expected, computed); 134 | } 135 | 136 | TEST_BEGIN(test_hash_x86_32) 137 | { 138 | 139 | hash_variant_verify(hash_variant_x86_32); 140 | } 141 | TEST_END 142 | 143 | TEST_BEGIN(test_hash_x86_128) 144 | { 145 | 146 | hash_variant_verify(hash_variant_x86_128); 147 | } 148 | TEST_END 149 | 150 | TEST_BEGIN(test_hash_x64_128) 151 | { 152 | 153 | hash_variant_verify(hash_variant_x64_128); 154 | } 155 | TEST_END 156 | 157 | int 158 | main(void) 159 | { 160 | 161 | return (test( 162 | test_hash_x86_32, 163 | test_hash_x86_128, 164 | test_hash_x64_128)); 165 | } 166 | -------------------------------------------------------------------------------- /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 allocm() 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 | return (test( 89 | test_mq_basic, 90 | test_mq_threaded)); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /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/unit/prof_accum.c: -------------------------------------------------------------------------------- 1 | #include "prof_accum.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 | #endif 7 | 8 | static int 9 | prof_dump_open_intercept(bool propagate_err, const char *filename) 10 | { 11 | int fd; 12 | 13 | fd = open("/dev/null", O_WRONLY); 14 | assert_d_ne(fd, -1, "Unexpected open() failure"); 15 | 16 | return (fd); 17 | } 18 | 19 | static void * 20 | alloc_from_permuted_backtrace(unsigned thd_ind, unsigned iteration) 21 | { 22 | 23 | return (alloc_0(thd_ind*NALLOCS_PER_THREAD + iteration)); 24 | } 25 | 26 | static void * 27 | thd_start(void *varg) 28 | { 29 | unsigned thd_ind = *(unsigned *)varg; 30 | size_t bt_count_prev, bt_count; 31 | unsigned i_prev, i; 32 | 33 | i_prev = 0; 34 | bt_count_prev = 0; 35 | for (i = 0; i < NALLOCS_PER_THREAD; i++) { 36 | void *p = alloc_from_permuted_backtrace(thd_ind, i); 37 | dallocx(p, 0); 38 | if (i % DUMP_INTERVAL == 0) { 39 | assert_d_eq(mallctl("prof.dump", NULL, NULL, NULL, 0), 40 | 0, "Unexpected error while dumping heap profile"); 41 | } 42 | 43 | if (i % BT_COUNT_CHECK_INTERVAL == 0 || 44 | i+1 == NALLOCS_PER_THREAD) { 45 | bt_count = prof_bt_count(); 46 | assert_zu_le(bt_count_prev+(i-i_prev), bt_count, 47 | "Expected larger backtrace count increase"); 48 | i_prev = i; 49 | bt_count_prev = bt_count; 50 | } 51 | } 52 | 53 | return (NULL); 54 | } 55 | 56 | TEST_BEGIN(test_idump) 57 | { 58 | bool active; 59 | thd_t thds[NTHREADS]; 60 | unsigned thd_args[NTHREADS]; 61 | unsigned i; 62 | 63 | test_skip_if(!config_prof); 64 | 65 | active = true; 66 | assert_d_eq(mallctl("prof.active", NULL, NULL, &active, sizeof(active)), 67 | 0, "Unexpected mallctl failure while activating profiling"); 68 | 69 | prof_dump_open = prof_dump_open_intercept; 70 | 71 | for (i = 0; i < NTHREADS; i++) { 72 | thd_args[i] = i; 73 | thd_create(&thds[i], thd_start, (void *)&thd_args[i]); 74 | } 75 | for (i = 0; i < NTHREADS; i++) 76 | thd_join(thds[i], NULL); 77 | } 78 | TEST_END 79 | 80 | int 81 | main(void) 82 | { 83 | 84 | return (test( 85 | test_idump)); 86 | } 87 | -------------------------------------------------------------------------------- /test/unit/prof_accum.h: -------------------------------------------------------------------------------- 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 | #define alloc_n_proto(n) \ 9 | void *alloc_##n(unsigned bits); 10 | alloc_n_proto(0) 11 | alloc_n_proto(1) 12 | 13 | #define alloc_n_gen(n) \ 14 | void * \ 15 | alloc_##n(unsigned bits) \ 16 | { \ 17 | void *p; \ 18 | \ 19 | if (bits == 0) \ 20 | p = mallocx(1, 0); \ 21 | else { \ 22 | switch (bits & 0x1U) { \ 23 | case 0: \ 24 | p = (alloc_0(bits >> 1)); \ 25 | break; \ 26 | case 1: \ 27 | p = (alloc_1(bits >> 1)); \ 28 | break; \ 29 | default: not_reached(); \ 30 | } \ 31 | } \ 32 | /* Intentionally sabotage tail call optimization. */ \ 33 | assert_ptr_not_null(p, "Unexpected mallocx() failure"); \ 34 | return (p); \ 35 | } 36 | -------------------------------------------------------------------------------- /test/unit/prof_accum_a.c: -------------------------------------------------------------------------------- 1 | #include "prof_accum.h" 2 | 3 | alloc_n_gen(0) 4 | -------------------------------------------------------------------------------- /test/unit/prof_accum_b.c: -------------------------------------------------------------------------------- 1 | #include "prof_accum.h" 2 | 3 | alloc_n_gen(1) 4 | -------------------------------------------------------------------------------- /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; 25 | void *p, *q; 26 | 27 | test_skip_if(!config_prof); 28 | 29 | active = true; 30 | assert_d_eq(mallctl("prof.active", NULL, NULL, &active, sizeof(active)), 31 | 0, "Unexpected mallctl failure while activating profiling"); 32 | 33 | prof_dump_open = prof_dump_open_intercept; 34 | 35 | did_prof_dump_open = false; 36 | p = mallocx(chunksize, 0); 37 | assert_ptr_not_null(p, "Unexpected mallocx() failure"); 38 | assert_true(did_prof_dump_open, "Expected a profile dump"); 39 | 40 | did_prof_dump_open = false; 41 | q = mallocx(chunksize, 0); 42 | assert_ptr_not_null(q, "Unexpected mallocx() failure"); 43 | assert_true(did_prof_dump_open, "Expected a profile dump"); 44 | 45 | dallocx(p, 0); 46 | dallocx(q, 0); 47 | } 48 | TEST_END 49 | 50 | int 51 | main(void) 52 | { 53 | 54 | return (test( 55 | test_gdump)); 56 | } 57 | -------------------------------------------------------------------------------- /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/unit/ql.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | /* Number of ring entries, in [2..26]. */ 4 | #define NENTRIES 9 5 | 6 | typedef struct list_s list_t; 7 | typedef ql_head(list_t) list_head_t; 8 | 9 | struct list_s { 10 | ql_elm(list_t) link; 11 | char id; 12 | }; 13 | 14 | static void 15 | test_empty_list(list_head_t *head) 16 | { 17 | list_t *t; 18 | unsigned i; 19 | 20 | assert_ptr_null(ql_first(head), "Unexpected element for empty list"); 21 | assert_ptr_null(ql_last(head, link), 22 | "Unexpected element for empty list"); 23 | 24 | i = 0; 25 | ql_foreach(t, head, link) { 26 | i++; 27 | } 28 | assert_u_eq(i, 0, "Unexpected element for empty list"); 29 | 30 | i = 0; 31 | ql_reverse_foreach(t, head, link) { 32 | i++; 33 | } 34 | assert_u_eq(i, 0, "Unexpected element for empty list"); 35 | } 36 | 37 | TEST_BEGIN(test_ql_empty) 38 | { 39 | list_head_t head; 40 | 41 | ql_new(&head); 42 | test_empty_list(&head); 43 | } 44 | TEST_END 45 | 46 | static void 47 | init_entries(list_t *entries, unsigned nentries) 48 | { 49 | unsigned i; 50 | 51 | for (i = 0; i < nentries; i++) { 52 | entries[i].id = 'a' + i; 53 | ql_elm_new(&entries[i], link); 54 | } 55 | } 56 | 57 | static void 58 | test_entries_list(list_head_t *head, list_t *entries, unsigned nentries) 59 | { 60 | list_t *t; 61 | unsigned i; 62 | 63 | assert_c_eq(ql_first(head)->id, entries[0].id, "Element id mismatch"); 64 | assert_c_eq(ql_last(head, link)->id, entries[nentries-1].id, 65 | "Element id mismatch"); 66 | 67 | i = 0; 68 | ql_foreach(t, head, link) { 69 | assert_c_eq(t->id, entries[i].id, "Element id mismatch"); 70 | i++; 71 | } 72 | 73 | i = 0; 74 | ql_reverse_foreach(t, head, link) { 75 | assert_c_eq(t->id, entries[nentries-i-1].id, 76 | "Element id mismatch"); 77 | i++; 78 | } 79 | 80 | for (i = 0; i < nentries-1; i++) { 81 | t = ql_next(head, &entries[i], link); 82 | assert_c_eq(t->id, entries[i+1].id, "Element id mismatch"); 83 | } 84 | assert_ptr_null(ql_next(head, &entries[nentries-1], link), 85 | "Unexpected element"); 86 | 87 | assert_ptr_null(ql_prev(head, &entries[0], link), "Unexpected element"); 88 | for (i = 1; i < nentries; i++) { 89 | t = ql_prev(head, &entries[i], link); 90 | assert_c_eq(t->id, entries[i-1].id, "Element id mismatch"); 91 | } 92 | } 93 | 94 | TEST_BEGIN(test_ql_tail_insert) 95 | { 96 | list_head_t head; 97 | list_t entries[NENTRIES]; 98 | unsigned i; 99 | 100 | ql_new(&head); 101 | init_entries(entries, sizeof(entries)/sizeof(list_t)); 102 | for (i = 0; i < NENTRIES; i++) 103 | ql_tail_insert(&head, &entries[i], link); 104 | 105 | test_entries_list(&head, entries, NENTRIES); 106 | } 107 | TEST_END 108 | 109 | TEST_BEGIN(test_ql_tail_remove) 110 | { 111 | list_head_t head; 112 | list_t entries[NENTRIES]; 113 | unsigned i; 114 | 115 | ql_new(&head); 116 | init_entries(entries, sizeof(entries)/sizeof(list_t)); 117 | for (i = 0; i < NENTRIES; i++) 118 | ql_tail_insert(&head, &entries[i], link); 119 | 120 | for (i = 0; i < NENTRIES; i++) { 121 | test_entries_list(&head, entries, NENTRIES-i); 122 | ql_tail_remove(&head, list_t, link); 123 | } 124 | test_empty_list(&head); 125 | } 126 | TEST_END 127 | 128 | TEST_BEGIN(test_ql_head_insert) 129 | { 130 | list_head_t head; 131 | list_t entries[NENTRIES]; 132 | unsigned i; 133 | 134 | ql_new(&head); 135 | init_entries(entries, sizeof(entries)/sizeof(list_t)); 136 | for (i = 0; i < NENTRIES; i++) 137 | ql_head_insert(&head, &entries[NENTRIES-i-1], link); 138 | 139 | test_entries_list(&head, entries, NENTRIES); 140 | } 141 | TEST_END 142 | 143 | TEST_BEGIN(test_ql_head_remove) 144 | { 145 | list_head_t head; 146 | list_t entries[NENTRIES]; 147 | unsigned i; 148 | 149 | ql_new(&head); 150 | init_entries(entries, sizeof(entries)/sizeof(list_t)); 151 | for (i = 0; i < NENTRIES; i++) 152 | ql_head_insert(&head, &entries[NENTRIES-i-1], link); 153 | 154 | for (i = 0; i < NENTRIES; i++) { 155 | test_entries_list(&head, &entries[i], NENTRIES-i); 156 | ql_head_remove(&head, list_t, link); 157 | } 158 | test_empty_list(&head); 159 | } 160 | TEST_END 161 | 162 | TEST_BEGIN(test_ql_insert) 163 | { 164 | list_head_t head; 165 | list_t entries[8]; 166 | list_t *a, *b, *c, *d, *e, *f, *g, *h; 167 | 168 | ql_new(&head); 169 | init_entries(entries, sizeof(entries)/sizeof(list_t)); 170 | a = &entries[0]; 171 | b = &entries[1]; 172 | c = &entries[2]; 173 | d = &entries[3]; 174 | e = &entries[4]; 175 | f = &entries[5]; 176 | g = &entries[6]; 177 | h = &entries[7]; 178 | 179 | /* 180 | * ql_remove(), ql_before_insert(), and ql_after_insert() are used 181 | * internally by other macros that are already tested, so there's no 182 | * need to test them completely. However, insertion/deletion from the 183 | * middle of lists is not otherwise tested; do so here. 184 | */ 185 | ql_tail_insert(&head, f, link); 186 | ql_before_insert(&head, f, b, link); 187 | ql_before_insert(&head, f, c, link); 188 | ql_after_insert(f, h, link); 189 | ql_after_insert(f, g, link); 190 | ql_before_insert(&head, b, a, link); 191 | ql_after_insert(c, d, link); 192 | ql_before_insert(&head, f, e, link); 193 | 194 | test_entries_list(&head, entries, sizeof(entries)/sizeof(list_t)); 195 | } 196 | TEST_END 197 | 198 | int 199 | main(void) 200 | { 201 | 202 | return (test( 203 | test_ql_empty, 204 | test_ql_tail_insert, 205 | test_ql_tail_remove, 206 | test_ql_head_insert, 207 | test_ql_head_remove, 208 | test_ql_insert)); 209 | } 210 | -------------------------------------------------------------------------------- /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 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/rtree.c: -------------------------------------------------------------------------------- 1 | #include "test/jemalloc_test.h" 2 | 3 | TEST_BEGIN(test_rtree_get_empty) 4 | { 5 | unsigned i; 6 | 7 | for (i = 1; i <= (sizeof(uintptr_t) << 3); i++) { 8 | rtree_t *rtree = rtree_new(i, imalloc, idalloc); 9 | assert_u_eq(rtree_get(rtree, 0), 0, 10 | "rtree_get() should return NULL for empty tree"); 11 | rtree_delete(rtree); 12 | } 13 | } 14 | TEST_END 15 | 16 | TEST_BEGIN(test_rtree_extrema) 17 | { 18 | unsigned i; 19 | 20 | for (i = 1; i <= (sizeof(uintptr_t) << 3); i++) { 21 | rtree_t *rtree = rtree_new(i, imalloc, idalloc); 22 | 23 | rtree_set(rtree, 0, 1); 24 | assert_u_eq(rtree_get(rtree, 0), 1, 25 | "rtree_get() should return previously set value"); 26 | 27 | rtree_set(rtree, ~((uintptr_t)0), 1); 28 | assert_u_eq(rtree_get(rtree, ~((uintptr_t)0)), 1, 29 | "rtree_get() should return previously set value"); 30 | 31 | rtree_delete(rtree); 32 | } 33 | } 34 | TEST_END 35 | 36 | TEST_BEGIN(test_rtree_bits) 37 | { 38 | unsigned i, j, k; 39 | 40 | for (i = 1; i < (sizeof(uintptr_t) << 3); i++) { 41 | uintptr_t keys[] = {0, 1, 42 | (((uintptr_t)1) << (sizeof(uintptr_t)*8-i)) - 1}; 43 | rtree_t *rtree = rtree_new(i, imalloc, idalloc); 44 | 45 | for (j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) { 46 | rtree_set(rtree, keys[j], 1); 47 | for (k = 0; k < sizeof(keys)/sizeof(uintptr_t); k++) { 48 | assert_u_eq(rtree_get(rtree, keys[k]), 1, 49 | "rtree_get() should return previously set " 50 | "value and ignore insignificant key bits; " 51 | "i=%u, j=%u, k=%u, set key=%#x, " 52 | "get key=%#x", i, j, k, keys[j], keys[k]); 53 | } 54 | assert_u_eq(rtree_get(rtree, 55 | (((uintptr_t)1) << (sizeof(uintptr_t)*8-i))), 0, 56 | "Only leftmost rtree leaf should be set; " 57 | "i=%u, j=%u", i, j); 58 | rtree_set(rtree, keys[j], 0); 59 | } 60 | 61 | rtree_delete(rtree); 62 | } 63 | } 64 | TEST_END 65 | 66 | TEST_BEGIN(test_rtree_random) 67 | { 68 | unsigned i; 69 | sfmt_t *sfmt; 70 | #define NSET 100 71 | #define SEED 42 72 | 73 | sfmt = init_gen_rand(SEED); 74 | for (i = 1; i <= (sizeof(uintptr_t) << 3); i++) { 75 | rtree_t *rtree = rtree_new(i, imalloc, idalloc); 76 | uintptr_t keys[NSET]; 77 | unsigned j; 78 | 79 | for (j = 0; j < NSET; j++) { 80 | keys[j] = (uintptr_t)gen_rand64(sfmt); 81 | rtree_set(rtree, keys[j], 1); 82 | assert_u_eq(rtree_get(rtree, keys[j]), 1, 83 | "rtree_get() should return previously set value"); 84 | } 85 | for (j = 0; j < NSET; j++) { 86 | assert_u_eq(rtree_get(rtree, keys[j]), 1, 87 | "rtree_get() should return previously set value"); 88 | } 89 | 90 | for (j = 0; j < NSET; j++) { 91 | rtree_set(rtree, keys[j], 0); 92 | assert_u_eq(rtree_get(rtree, keys[j]), 0, 93 | "rtree_get() should return previously set value"); 94 | } 95 | for (j = 0; j < NSET; j++) { 96 | assert_u_eq(rtree_get(rtree, keys[j]), 0, 97 | "rtree_get() should return previously set value"); 98 | } 99 | 100 | rtree_delete(rtree); 101 | } 102 | fini_gen_rand(sfmt); 103 | #undef NSET 104 | #undef SEED 105 | } 106 | TEST_END 107 | 108 | int 109 | main(void) 110 | { 111 | 112 | return (test( 113 | test_rtree_get_empty, 114 | test_rtree_extrema, 115 | test_rtree_bits, 116 | test_rtree_random)); 117 | } 118 | -------------------------------------------------------------------------------- /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 | void 10 | data_cleanup(void *arg) 11 | { 12 | data_t *data = (data_t *)arg; 13 | 14 | assert_x_eq(*data, THREAD_DATA, 15 | "Argument passed into cleanup function should match tsd value"); 16 | data_cleanup_executed = true; 17 | } 18 | 19 | malloc_tsd_protos(, data, data_t) 20 | malloc_tsd_externs(data, data_t) 21 | #define DATA_INIT 0x12345678 22 | malloc_tsd_data(, data, data_t, DATA_INIT) 23 | malloc_tsd_funcs(, data, data_t, DATA_INIT, data_cleanup) 24 | 25 | static void * 26 | thd_start(void *arg) 27 | { 28 | data_t d = (data_t)(uintptr_t)arg; 29 | assert_x_eq(*data_tsd_get(), DATA_INIT, 30 | "Initial tsd get should return initialization value"); 31 | 32 | data_tsd_set(&d); 33 | assert_x_eq(*data_tsd_get(), d, 34 | "After tsd set, tsd get should return value that was set"); 35 | 36 | d = 0; 37 | assert_x_eq(*data_tsd_get(), (data_t)(uintptr_t)arg, 38 | "Resetting local data should have no effect on tsd"); 39 | 40 | return (NULL); 41 | } 42 | 43 | TEST_BEGIN(test_tsd_main_thread) 44 | { 45 | 46 | thd_start((void *) 0xa5f3e329); 47 | } 48 | TEST_END 49 | 50 | TEST_BEGIN(test_tsd_sub_thread) 51 | { 52 | thd_t thd; 53 | 54 | data_cleanup_executed = false; 55 | thd_create(&thd, thd_start, (void *)THREAD_DATA); 56 | thd_join(thd, NULL); 57 | assert_true(data_cleanup_executed, 58 | "Cleanup function should have executed"); 59 | } 60 | TEST_END 61 | 62 | int 63 | main(void) 64 | { 65 | 66 | data_tsd_boot(); 67 | 68 | return (test( 69 | test_tsd_main_thread, 70 | test_tsd_sub_thread)); 71 | } 72 | -------------------------------------------------------------------------------- /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 | char *s; 12 | size_t sz_prev, sz, i; 13 | 14 | sz_prev = 0; 15 | s = (char *)mallocx(sz_min, 0); 16 | assert_ptr_not_null((void *)s, "Unexpected mallocx() failure"); 17 | 18 | for (sz = sallocx(s, 0); sz <= sz_max; 19 | sz_prev = sz, sz = sallocx(s, 0)) { 20 | if (sz_prev > 0) { 21 | assert_c_eq(s[0], 'a', 22 | "Previously allocated byte %zu/%zu is corrupted", 23 | 0, sz_prev); 24 | assert_c_eq(s[sz_prev-1], 'a', 25 | "Previously allocated byte %zu/%zu is corrupted", 26 | sz_prev-1, sz_prev); 27 | } 28 | 29 | for (i = sz_prev; i < sz; i++) { 30 | assert_c_eq(s[i], 0x0, 31 | "Newly allocated byte %zu/%zu isn't zero-filled", 32 | i, sz); 33 | s[i] = 'a'; 34 | } 35 | 36 | if (xallocx(s, sz+1, 0, 0) == sz) { 37 | s = (char *)rallocx(s, sz+1, 0); 38 | assert_ptr_not_null((void *)s, 39 | "Unexpected rallocx() failure"); 40 | } 41 | } 42 | 43 | dallocx(s, 0); 44 | } 45 | 46 | TEST_BEGIN(test_zero_small) 47 | { 48 | 49 | test_skip_if(!config_fill); 50 | test_zero(1, SMALL_MAXCLASS-1); 51 | } 52 | TEST_END 53 | 54 | TEST_BEGIN(test_zero_large) 55 | { 56 | 57 | test_skip_if(!config_fill); 58 | test_zero(SMALL_MAXCLASS+1, arena_maxclass); 59 | } 60 | TEST_END 61 | 62 | TEST_BEGIN(test_zero_huge) 63 | { 64 | 65 | test_skip_if(!config_fill); 66 | test_zero(arena_maxclass+1, chunksize*2); 67 | } 68 | TEST_END 69 | 70 | int 71 | main(void) 72 | { 73 | 74 | return (test( 75 | test_zero_small, 76 | test_zero_large, 77 | test_zero_huge)); 78 | } 79 | --------------------------------------------------------------------------------