Home | History | Annotate | Download | only in internal
      1 #ifndef JEMALLOC_INTERNAL_H
      2 #define	JEMALLOC_INTERNAL_H
      3 
      4 #include "jemalloc_internal_defs.h"
      5 #include "jemalloc/internal/jemalloc_internal_decls.h"
      6 
      7 #ifdef JEMALLOC_UTRACE
      8 #include <sys/ktrace.h>
      9 #endif
     10 
     11 #define	JEMALLOC_NO_DEMANGLE
     12 #ifdef JEMALLOC_JET
     13 #  define JEMALLOC_N(n) jet_##n
     14 #  include "jemalloc/internal/public_namespace.h"
     15 #  define JEMALLOC_NO_RENAME
     16 #  include "../jemalloc.h"
     17 #  undef JEMALLOC_NO_RENAME
     18 #else
     19 #  define JEMALLOC_N(n) je_##n
     20 #  include "../jemalloc.h"
     21 #endif
     22 #include "jemalloc/internal/private_namespace.h"
     23 
     24 static const bool config_debug =
     25 #ifdef JEMALLOC_DEBUG
     26     true
     27 #else
     28     false
     29 #endif
     30     ;
     31 static const bool have_dss =
     32 #ifdef JEMALLOC_DSS
     33     true
     34 #else
     35     false
     36 #endif
     37     ;
     38 static const bool config_fill =
     39 #ifdef JEMALLOC_FILL
     40     true
     41 #else
     42     false
     43 #endif
     44     ;
     45 static const bool config_lazy_lock =
     46 #ifdef JEMALLOC_LAZY_LOCK
     47     true
     48 #else
     49     false
     50 #endif
     51     ;
     52 static const bool config_prof =
     53 #ifdef JEMALLOC_PROF
     54     true
     55 #else
     56     false
     57 #endif
     58     ;
     59 static const bool config_prof_libgcc =
     60 #ifdef JEMALLOC_PROF_LIBGCC
     61     true
     62 #else
     63     false
     64 #endif
     65     ;
     66 static const bool config_prof_libunwind =
     67 #ifdef JEMALLOC_PROF_LIBUNWIND
     68     true
     69 #else
     70     false
     71 #endif
     72     ;
     73 static const bool config_munmap =
     74 #ifdef JEMALLOC_MUNMAP
     75     true
     76 #else
     77     false
     78 #endif
     79     ;
     80 static const bool config_stats =
     81 #ifdef JEMALLOC_STATS
     82     true
     83 #else
     84     false
     85 #endif
     86     ;
     87 static const bool config_tcache =
     88 #ifdef JEMALLOC_TCACHE
     89     true
     90 #else
     91     false
     92 #endif
     93     ;
     94 static const bool config_tls =
     95 #ifdef JEMALLOC_TLS
     96     true
     97 #else
     98     false
     99 #endif
    100     ;
    101 static const bool config_utrace =
    102 #ifdef JEMALLOC_UTRACE
    103     true
    104 #else
    105     false
    106 #endif
    107     ;
    108 static const bool config_valgrind =
    109 #ifdef JEMALLOC_VALGRIND
    110     true
    111 #else
    112     false
    113 #endif
    114     ;
    115 static const bool config_xmalloc =
    116 #ifdef JEMALLOC_XMALLOC
    117     true
    118 #else
    119     false
    120 #endif
    121     ;
    122 static const bool config_ivsalloc =
    123 #ifdef JEMALLOC_IVSALLOC
    124     true
    125 #else
    126     false
    127 #endif
    128     ;
    129 
    130 #ifdef JEMALLOC_ATOMIC9
    131 #include <machine/atomic.h>
    132 #endif
    133 
    134 #if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN))
    135 #include <libkern/OSAtomic.h>
    136 #endif
    137 
    138 #ifdef JEMALLOC_ZONE
    139 #include <mach/mach_error.h>
    140 #include <mach/mach_init.h>
    141 #include <mach/vm_map.h>
    142 #include <malloc/malloc.h>
    143 #endif
    144 
    145 #define	RB_COMPACT
    146 #include "jemalloc/internal/rb.h"
    147 #include "jemalloc/internal/qr.h"
    148 #include "jemalloc/internal/ql.h"
    149 
    150 /*
    151  * jemalloc can conceptually be broken into components (arena, tcache, etc.),
    152  * but there are circular dependencies that cannot be broken without
    153  * substantial performance degradation.  In order to reduce the effect on
    154  * visual code flow, read the header files in multiple passes, with one of the
    155  * following cpp variables defined during each pass:
    156  *
    157  *   JEMALLOC_H_TYPES   : Preprocessor-defined constants and psuedo-opaque data
    158  *                        types.
    159  *   JEMALLOC_H_STRUCTS : Data structures.
    160  *   JEMALLOC_H_EXTERNS : Extern data declarations and function prototypes.
    161  *   JEMALLOC_H_INLINES : Inline functions.
    162  */
    163 /******************************************************************************/
    164 #define	JEMALLOC_H_TYPES
    165 
    166 #include "jemalloc/internal/jemalloc_internal_macros.h"
    167 
    168 #define	MALLOCX_LG_ALIGN_MASK	((int)0x3f)
    169 
    170 /* Smallest size class to support. */
    171 #define	LG_TINY_MIN		3
    172 #define	TINY_MIN		(1U << LG_TINY_MIN)
    173 
    174 /*
    175  * Minimum alignment of allocations is 2^LG_QUANTUM bytes (ignoring tiny size
    176  * classes).
    177  */
    178 #ifndef LG_QUANTUM
    179 #  if (defined(__i386__) || defined(_M_IX86))
    180 #    define LG_QUANTUM		4
    181 #  endif
    182 #  ifdef __ia64__
    183 #    define LG_QUANTUM		4
    184 #  endif
    185 #  ifdef __alpha__
    186 #    define LG_QUANTUM		4
    187 #  endif
    188 #  ifdef __sparc64__
    189 #    define LG_QUANTUM		4
    190 #  endif
    191 #  if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64))
    192 #    define LG_QUANTUM		4
    193 #  endif
    194 #  ifdef __arm__
    195 #    define LG_QUANTUM		3
    196 #  endif
    197 #  ifdef __aarch64__
    198 #    define LG_QUANTUM		4
    199 #  endif
    200 #  ifdef __hppa__
    201 #    define LG_QUANTUM		4
    202 #  endif
    203 #  ifdef __mips__
    204 #    define LG_QUANTUM		3
    205 #  endif
    206 #  ifdef __powerpc__
    207 #    define LG_QUANTUM		4
    208 #  endif
    209 #  ifdef __s390__
    210 #    define LG_QUANTUM		4
    211 #  endif
    212 #  ifdef __SH4__
    213 #    define LG_QUANTUM		4
    214 #  endif
    215 #  ifdef __tile__
    216 #    define LG_QUANTUM		4
    217 #  endif
    218 #  ifdef __le32__
    219 #    define LG_QUANTUM		4
    220 #  endif
    221 #  ifndef LG_QUANTUM
    222 #    error "No LG_QUANTUM definition for architecture; specify via CPPFLAGS"
    223 #  endif
    224 #endif
    225 
    226 #define	QUANTUM			((size_t)(1U << LG_QUANTUM))
    227 #define	QUANTUM_MASK		(QUANTUM - 1)
    228 
    229 /* Return the smallest quantum multiple that is >= a. */
    230 #define	QUANTUM_CEILING(a)						\
    231 	(((a) + QUANTUM_MASK) & ~QUANTUM_MASK)
    232 
    233 #define	LONG			((size_t)(1U << LG_SIZEOF_LONG))
    234 #define	LONG_MASK		(LONG - 1)
    235 
    236 /* Return the smallest long multiple that is >= a. */
    237 #define	LONG_CEILING(a)							\
    238 	(((a) + LONG_MASK) & ~LONG_MASK)
    239 
    240 #define	SIZEOF_PTR		(1U << LG_SIZEOF_PTR)
    241 #define	PTR_MASK		(SIZEOF_PTR - 1)
    242 
    243 /* Return the smallest (void *) multiple that is >= a. */
    244 #define	PTR_CEILING(a)							\
    245 	(((a) + PTR_MASK) & ~PTR_MASK)
    246 
    247 /*
    248  * Maximum size of L1 cache line.  This is used to avoid cache line aliasing.
    249  * In addition, this controls the spacing of cacheline-spaced size classes.
    250  *
    251  * CACHELINE cannot be based on LG_CACHELINE because __declspec(align()) can
    252  * only handle raw constants.
    253  */
    254 #define	LG_CACHELINE		6
    255 #define	CACHELINE		64
    256 #define	CACHELINE_MASK		(CACHELINE - 1)
    257 
    258 /* Return the smallest cacheline multiple that is >= s. */
    259 #define	CACHELINE_CEILING(s)						\
    260 	(((s) + CACHELINE_MASK) & ~CACHELINE_MASK)
    261 
    262 /* Page size.  STATIC_PAGE_SHIFT is determined by the configure script. */
    263 #ifdef PAGE_MASK
    264 #  undef PAGE_MASK
    265 #endif
    266 #define	LG_PAGE		STATIC_PAGE_SHIFT
    267 #define	PAGE		((size_t)(1U << STATIC_PAGE_SHIFT))
    268 #define	PAGE_MASK	((size_t)(PAGE - 1))
    269 
    270 /* Return the smallest pagesize multiple that is >= s. */
    271 #define	PAGE_CEILING(s)							\
    272 	(((s) + PAGE_MASK) & ~PAGE_MASK)
    273 
    274 /* Return the nearest aligned address at or below a. */
    275 #define	ALIGNMENT_ADDR2BASE(a, alignment)				\
    276 	((void *)((uintptr_t)(a) & (-(alignment))))
    277 
    278 /* Return the offset between a and the nearest aligned address at or below a. */
    279 #define	ALIGNMENT_ADDR2OFFSET(a, alignment)				\
    280 	((size_t)((uintptr_t)(a) & (alignment - 1)))
    281 
    282 /* Return the smallest alignment multiple that is >= s. */
    283 #define	ALIGNMENT_CEILING(s, alignment)					\
    284 	(((s) + (alignment - 1)) & (-(alignment)))
    285 
    286 /* Declare a variable length array */
    287 #if __STDC_VERSION__ < 199901L
    288 #  ifdef _MSC_VER
    289 #    include <malloc.h>
    290 #    define alloca _alloca
    291 #  else
    292 #    ifdef JEMALLOC_HAS_ALLOCA_H
    293 #      include <alloca.h>
    294 #    else
    295 #      include <stdlib.h>
    296 #    endif
    297 #  endif
    298 #  define VARIABLE_ARRAY(type, name, count) \
    299 	type *name = alloca(sizeof(type) * (count))
    300 #else
    301 #  define VARIABLE_ARRAY(type, name, count) type name[(count)]
    302 #endif
    303 
    304 #include "jemalloc/internal/valgrind.h"
    305 #include "jemalloc/internal/util.h"
    306 #include "jemalloc/internal/atomic.h"
    307 #include "jemalloc/internal/prng.h"
    308 #include "jemalloc/internal/ckh.h"
    309 #include "jemalloc/internal/size_classes.h"
    310 #include "jemalloc/internal/stats.h"
    311 #include "jemalloc/internal/ctl.h"
    312 #include "jemalloc/internal/mutex.h"
    313 #include "jemalloc/internal/tsd.h"
    314 #include "jemalloc/internal/mb.h"
    315 #include "jemalloc/internal/extent.h"
    316 #include "jemalloc/internal/arena.h"
    317 #include "jemalloc/internal/bitmap.h"
    318 #include "jemalloc/internal/base.h"
    319 #include "jemalloc/internal/chunk.h"
    320 #include "jemalloc/internal/huge.h"
    321 #include "jemalloc/internal/rtree.h"
    322 #include "jemalloc/internal/tcache.h"
    323 #include "jemalloc/internal/hash.h"
    324 #include "jemalloc/internal/quarantine.h"
    325 #include "jemalloc/internal/prof.h"
    326 
    327 #undef JEMALLOC_H_TYPES
    328 /******************************************************************************/
    329 #define	JEMALLOC_H_STRUCTS
    330 
    331 #include "jemalloc/internal/valgrind.h"
    332 #include "jemalloc/internal/util.h"
    333 #include "jemalloc/internal/atomic.h"
    334 #include "jemalloc/internal/prng.h"
    335 #include "jemalloc/internal/ckh.h"
    336 #include "jemalloc/internal/size_classes.h"
    337 #include "jemalloc/internal/stats.h"
    338 #include "jemalloc/internal/ctl.h"
    339 #include "jemalloc/internal/mutex.h"
    340 #include "jemalloc/internal/tsd.h"
    341 #include "jemalloc/internal/mb.h"
    342 #include "jemalloc/internal/bitmap.h"
    343 #include "jemalloc/internal/extent.h"
    344 #include "jemalloc/internal/arena.h"
    345 #include "jemalloc/internal/base.h"
    346 #include "jemalloc/internal/chunk.h"
    347 #include "jemalloc/internal/huge.h"
    348 #include "jemalloc/internal/rtree.h"
    349 #include "jemalloc/internal/tcache.h"
    350 #include "jemalloc/internal/hash.h"
    351 #include "jemalloc/internal/quarantine.h"
    352 #include "jemalloc/internal/prof.h"
    353 
    354 typedef struct {
    355 	uint64_t	allocated;
    356 	uint64_t	deallocated;
    357 } thread_allocated_t;
    358 /*
    359  * The JEMALLOC_ARG_CONCAT() wrapper is necessary to pass {0, 0} via a cpp macro
    360  * argument.
    361  */
    362 #define	THREAD_ALLOCATED_INITIALIZER	JEMALLOC_ARG_CONCAT({0, 0})
    363 
    364 #undef JEMALLOC_H_STRUCTS
    365 /******************************************************************************/
    366 #define	JEMALLOC_H_EXTERNS
    367 
    368 extern bool	opt_abort;
    369 extern bool	opt_junk;
    370 extern size_t	opt_quarantine;
    371 extern bool	opt_redzone;
    372 extern bool	opt_utrace;
    373 extern bool	opt_xmalloc;
    374 extern bool	opt_zero;
    375 extern size_t	opt_narenas;
    376 
    377 extern bool	in_valgrind;
    378 
    379 /* Number of CPUs. */
    380 extern unsigned		ncpus;
    381 
    382 /* Protects arenas initialization (arenas, arenas_total). */
    383 extern malloc_mutex_t	arenas_lock;
    384 /*
    385  * Arenas that are used to service external requests.  Not all elements of the
    386  * arenas array are necessarily used; arenas are created lazily as needed.
    387  *
    388  * arenas[0..narenas_auto) are used for automatic multiplexing of threads and
    389  * arenas.  arenas[narenas_auto..narenas_total) are only used if the application
    390  * takes some action to create them and allocate from them.
    391  */
    392 extern arena_t		**arenas;
    393 extern unsigned		narenas_total;
    394 extern unsigned		narenas_auto; /* Read-only after initialization. */
    395 
    396 arena_t	*arenas_extend(unsigned ind);
    397 void	arenas_cleanup(void *arg);
    398 arena_t	*choose_arena_hard(void);
    399 void	jemalloc_prefork(void);
    400 void	jemalloc_postfork_parent(void);
    401 void	jemalloc_postfork_child(void);
    402 
    403 #include "jemalloc/internal/valgrind.h"
    404 #include "jemalloc/internal/util.h"
    405 #include "jemalloc/internal/atomic.h"
    406 #include "jemalloc/internal/prng.h"
    407 #include "jemalloc/internal/ckh.h"
    408 #include "jemalloc/internal/size_classes.h"
    409 #include "jemalloc/internal/stats.h"
    410 #include "jemalloc/internal/ctl.h"
    411 #include "jemalloc/internal/mutex.h"
    412 #include "jemalloc/internal/tsd.h"
    413 #include "jemalloc/internal/mb.h"
    414 #include "jemalloc/internal/bitmap.h"
    415 #include "jemalloc/internal/extent.h"
    416 #include "jemalloc/internal/arena.h"
    417 #include "jemalloc/internal/base.h"
    418 #include "jemalloc/internal/chunk.h"
    419 #include "jemalloc/internal/huge.h"
    420 #include "jemalloc/internal/rtree.h"
    421 #include "jemalloc/internal/tcache.h"
    422 #include "jemalloc/internal/hash.h"
    423 #include "jemalloc/internal/quarantine.h"
    424 #include "jemalloc/internal/prof.h"
    425 
    426 #undef JEMALLOC_H_EXTERNS
    427 /******************************************************************************/
    428 #define	JEMALLOC_H_INLINES
    429 
    430 #include "jemalloc/internal/valgrind.h"
    431 #include "jemalloc/internal/util.h"
    432 #include "jemalloc/internal/atomic.h"
    433 #include "jemalloc/internal/prng.h"
    434 #include "jemalloc/internal/ckh.h"
    435 #include "jemalloc/internal/size_classes.h"
    436 #include "jemalloc/internal/stats.h"
    437 #include "jemalloc/internal/ctl.h"
    438 #include "jemalloc/internal/mutex.h"
    439 #include "jemalloc/internal/tsd.h"
    440 #include "jemalloc/internal/mb.h"
    441 #include "jemalloc/internal/extent.h"
    442 #include "jemalloc/internal/base.h"
    443 #include "jemalloc/internal/chunk.h"
    444 #include "jemalloc/internal/huge.h"
    445 
    446 /*
    447  * Include arena.h the first time in order to provide inline functions for this
    448  * header's inlines.
    449  */
    450 #define	JEMALLOC_ARENA_INLINE_A
    451 #include "jemalloc/internal/arena.h"
    452 #undef JEMALLOC_ARENA_INLINE_A
    453 
    454 #ifndef JEMALLOC_ENABLE_INLINE
    455 malloc_tsd_protos(JEMALLOC_ATTR(unused), arenas, arena_t *)
    456 
    457 size_t	s2u(size_t size);
    458 size_t	sa2u(size_t size, size_t alignment);
    459 unsigned	narenas_total_get(void);
    460 arena_t	*choose_arena(arena_t *arena);
    461 #endif
    462 
    463 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
    464 /*
    465  * Map of pthread_self() --> arenas[???], used for selecting an arena to use
    466  * for allocations.
    467  */
    468 malloc_tsd_externs(arenas, arena_t *)
    469 malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, arenas, arena_t *, NULL,
    470     arenas_cleanup)
    471 
    472 /*
    473  * Compute usable size that would result from allocating an object with the
    474  * specified size.
    475  */
    476 JEMALLOC_ALWAYS_INLINE size_t
    477 s2u(size_t size)
    478 {
    479 
    480 	if (size <= SMALL_MAXCLASS)
    481 		return (small_s2u(size));
    482 	if (size <= arena_maxclass)
    483 		return (PAGE_CEILING(size));
    484 	return (CHUNK_CEILING(size));
    485 }
    486 
    487 /*
    488  * Compute usable size that would result from allocating an object with the
    489  * specified size and alignment.
    490  */
    491 JEMALLOC_ALWAYS_INLINE size_t
    492 sa2u(size_t size, size_t alignment)
    493 {
    494 	size_t usize;
    495 
    496 	assert(alignment != 0 && ((alignment - 1) & alignment) == 0);
    497 
    498 	/*
    499 	 * Round size up to the nearest multiple of alignment.
    500 	 *
    501 	 * This done, we can take advantage of the fact that for each small
    502 	 * size class, every object is aligned at the smallest power of two
    503 	 * that is non-zero in the base two representation of the size.  For
    504 	 * example:
    505 	 *
    506 	 *   Size |   Base 2 | Minimum alignment
    507 	 *   -----+----------+------------------
    508 	 *     96 |  1100000 |  32
    509 	 *    144 | 10100000 |  32
    510 	 *    192 | 11000000 |  64
    511 	 */
    512 	usize = ALIGNMENT_CEILING(size, alignment);
    513 	/*
    514 	 * (usize < size) protects against the combination of maximal
    515 	 * alignment and size greater than maximal alignment.
    516 	 */
    517 	if (usize < size) {
    518 		/* size_t overflow. */
    519 		return (0);
    520 	}
    521 
    522 	if (usize <= arena_maxclass && alignment <= PAGE) {
    523 		if (usize <= SMALL_MAXCLASS)
    524 			return (small_s2u(usize));
    525 		return (PAGE_CEILING(usize));
    526 	} else {
    527 		size_t run_size;
    528 
    529 		/*
    530 		 * We can't achieve subpage alignment, so round up alignment
    531 		 * permanently; it makes later calculations simpler.
    532 		 */
    533 		alignment = PAGE_CEILING(alignment);
    534 		usize = PAGE_CEILING(size);
    535 		/*
    536 		 * (usize < size) protects against very large sizes within
    537 		 * PAGE of SIZE_T_MAX.
    538 		 *
    539 		 * (usize + alignment < usize) protects against the
    540 		 * combination of maximal alignment and usize large enough
    541 		 * to cause overflow.  This is similar to the first overflow
    542 		 * check above, but it needs to be repeated due to the new
    543 		 * usize value, which may now be *equal* to maximal
    544 		 * alignment, whereas before we only detected overflow if the
    545 		 * original size was *greater* than maximal alignment.
    546 		 */
    547 		if (usize < size || usize + alignment < usize) {
    548 			/* size_t overflow. */
    549 			return (0);
    550 		}
    551 
    552 		/*
    553 		 * Calculate the size of the over-size run that arena_palloc()
    554 		 * would need to allocate in order to guarantee the alignment.
    555 		 * If the run wouldn't fit within a chunk, round up to a huge
    556 		 * allocation size.
    557 		 */
    558 		run_size = usize + alignment - PAGE;
    559 		if (run_size <= arena_maxclass)
    560 			return (PAGE_CEILING(usize));
    561 		return (CHUNK_CEILING(usize));
    562 	}
    563 }
    564 
    565 JEMALLOC_INLINE unsigned
    566 narenas_total_get(void)
    567 {
    568 	unsigned narenas;
    569 
    570 	malloc_mutex_lock(&arenas_lock);
    571 	narenas = narenas_total;
    572 	malloc_mutex_unlock(&arenas_lock);
    573 
    574 	return (narenas);
    575 }
    576 
    577 /* Choose an arena based on a per-thread value. */
    578 JEMALLOC_INLINE arena_t *
    579 choose_arena(arena_t *arena)
    580 {
    581 	arena_t *ret;
    582 
    583 	if (arena != NULL)
    584 		return (arena);
    585 
    586 	if ((ret = *arenas_tsd_get()) == NULL) {
    587 		ret = choose_arena_hard();
    588 		assert(ret != NULL);
    589 	}
    590 
    591 	return (ret);
    592 }
    593 #endif
    594 
    595 #include "jemalloc/internal/bitmap.h"
    596 #include "jemalloc/internal/rtree.h"
    597 /*
    598  * Include arena.h the second and third times in order to resolve circular
    599  * dependencies with tcache.h.
    600  */
    601 #define	JEMALLOC_ARENA_INLINE_B
    602 #include "jemalloc/internal/arena.h"
    603 #undef JEMALLOC_ARENA_INLINE_B
    604 #include "jemalloc/internal/tcache.h"
    605 #define	JEMALLOC_ARENA_INLINE_C
    606 #include "jemalloc/internal/arena.h"
    607 #undef JEMALLOC_ARENA_INLINE_C
    608 #include "jemalloc/internal/hash.h"
    609 #include "jemalloc/internal/quarantine.h"
    610 
    611 #ifndef JEMALLOC_ENABLE_INLINE
    612 void	*imalloct(size_t size, bool try_tcache, arena_t *arena);
    613 void	*imalloc(size_t size);
    614 void	*icalloct(size_t size, bool try_tcache, arena_t *arena);
    615 void	*icalloc(size_t size);
    616 void	*ipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache,
    617     arena_t *arena);
    618 void	*ipalloc(size_t usize, size_t alignment, bool zero);
    619 size_t	isalloc(const void *ptr, bool demote);
    620 size_t	ivsalloc(const void *ptr, bool demote);
    621 size_t	u2rz(size_t usize);
    622 size_t	p2rz(const void *ptr);
    623 void	idalloct(void *ptr, bool try_tcache);
    624 void	idalloc(void *ptr);
    625 void	iqalloct(void *ptr, bool try_tcache);
    626 void	iqalloc(void *ptr);
    627 void	*iralloct_realign(void *ptr, size_t oldsize, size_t size, size_t extra,
    628     size_t alignment, bool zero, bool try_tcache_alloc, bool try_tcache_dalloc,
    629     arena_t *arena);
    630 void	*iralloct(void *ptr, size_t size, size_t extra, size_t alignment,
    631     bool zero, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena);
    632 void	*iralloc(void *ptr, size_t size, size_t extra, size_t alignment,
    633     bool zero);
    634 bool	ixalloc(void *ptr, size_t size, size_t extra, size_t alignment,
    635     bool zero);
    636 malloc_tsd_protos(JEMALLOC_ATTR(unused), thread_allocated, thread_allocated_t)
    637 #endif
    638 
    639 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
    640 JEMALLOC_ALWAYS_INLINE void *
    641 imalloct(size_t size, bool try_tcache, arena_t *arena)
    642 {
    643 
    644 	assert(size != 0);
    645 
    646 	if (size <= arena_maxclass)
    647 		return (arena_malloc(arena, size, false, try_tcache));
    648 	else
    649 		return (huge_malloc(arena, size, false));
    650 }
    651 
    652 JEMALLOC_ALWAYS_INLINE void *
    653 imalloc(size_t size)
    654 {
    655 
    656 	return (imalloct(size, true, NULL));
    657 }
    658 
    659 JEMALLOC_ALWAYS_INLINE void *
    660 icalloct(size_t size, bool try_tcache, arena_t *arena)
    661 {
    662 
    663 	if (size <= arena_maxclass)
    664 		return (arena_malloc(arena, size, true, try_tcache));
    665 	else
    666 		return (huge_malloc(arena, size, true));
    667 }
    668 
    669 JEMALLOC_ALWAYS_INLINE void *
    670 icalloc(size_t size)
    671 {
    672 
    673 	return (icalloct(size, true, NULL));
    674 }
    675 
    676 JEMALLOC_ALWAYS_INLINE void *
    677 ipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache,
    678     arena_t *arena)
    679 {
    680 	void *ret;
    681 
    682 	assert(usize != 0);
    683 	assert(usize == sa2u(usize, alignment));
    684 
    685 	if (usize <= arena_maxclass && alignment <= PAGE)
    686 		ret = arena_malloc(arena, usize, zero, try_tcache);
    687 	else {
    688 		if (usize <= arena_maxclass) {
    689 			ret = arena_palloc(choose_arena(arena), usize,
    690 			    alignment, zero);
    691 		} else if (alignment <= chunksize)
    692 			ret = huge_malloc(arena, usize, zero);
    693 		else
    694 			ret = huge_palloc(arena, usize, alignment, zero);
    695 	}
    696 
    697 	assert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret);
    698 	return (ret);
    699 }
    700 
    701 JEMALLOC_ALWAYS_INLINE void *
    702 ipalloc(size_t usize, size_t alignment, bool zero)
    703 {
    704 
    705 	return (ipalloct(usize, alignment, zero, true, NULL));
    706 }
    707 
    708 /*
    709  * Typical usage:
    710  *   void *ptr = [...]
    711  *   size_t sz = isalloc(ptr, config_prof);
    712  */
    713 JEMALLOC_ALWAYS_INLINE size_t
    714 isalloc(const void *ptr, bool demote)
    715 {
    716 	size_t ret;
    717 	arena_chunk_t *chunk;
    718 
    719 	assert(ptr != NULL);
    720 	/* Demotion only makes sense if config_prof is true. */
    721 	assert(config_prof || demote == false);
    722 
    723 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
    724 	if (chunk != ptr)
    725 		ret = arena_salloc(ptr, demote);
    726 	else
    727 		ret = huge_salloc(ptr);
    728 
    729 	return (ret);
    730 }
    731 
    732 JEMALLOC_ALWAYS_INLINE size_t
    733 ivsalloc(const void *ptr, bool demote)
    734 {
    735 
    736 	/* Return 0 if ptr is not within a chunk managed by jemalloc. */
    737 	if (rtree_get(chunks_rtree, (uintptr_t)CHUNK_ADDR2BASE(ptr)) == 0)
    738 		return (0);
    739 
    740 	return (isalloc(ptr, demote));
    741 }
    742 
    743 JEMALLOC_INLINE size_t
    744 u2rz(size_t usize)
    745 {
    746 	size_t ret;
    747 
    748 	if (usize <= SMALL_MAXCLASS) {
    749 		size_t binind = small_size2bin(usize);
    750 		ret = arena_bin_info[binind].redzone_size;
    751 	} else
    752 		ret = 0;
    753 
    754 	return (ret);
    755 }
    756 
    757 JEMALLOC_INLINE size_t
    758 p2rz(const void *ptr)
    759 {
    760 	size_t usize = isalloc(ptr, false);
    761 
    762 	return (u2rz(usize));
    763 }
    764 
    765 JEMALLOC_ALWAYS_INLINE void
    766 idalloct(void *ptr, bool try_tcache)
    767 {
    768 	arena_chunk_t *chunk;
    769 
    770 	assert(ptr != NULL);
    771 
    772 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
    773 	if (chunk != ptr)
    774 		arena_dalloc(chunk, ptr, try_tcache);
    775 	else
    776 		huge_dalloc(ptr);
    777 }
    778 
    779 JEMALLOC_ALWAYS_INLINE void
    780 idalloc(void *ptr)
    781 {
    782 
    783 	idalloct(ptr, true);
    784 }
    785 
    786 JEMALLOC_ALWAYS_INLINE void
    787 iqalloct(void *ptr, bool try_tcache)
    788 {
    789 
    790 	if (config_fill && opt_quarantine)
    791 		quarantine(ptr);
    792 	else
    793 		idalloct(ptr, try_tcache);
    794 }
    795 
    796 JEMALLOC_ALWAYS_INLINE void
    797 iqalloc(void *ptr)
    798 {
    799 
    800 	iqalloct(ptr, true);
    801 }
    802 
    803 JEMALLOC_ALWAYS_INLINE void *
    804 iralloct_realign(void *ptr, size_t oldsize, size_t size, size_t extra,
    805     size_t alignment, bool zero, bool try_tcache_alloc, bool try_tcache_dalloc,
    806     arena_t *arena)
    807 {
    808 	void *p;
    809 	size_t usize, copysize;
    810 
    811 	usize = sa2u(size + extra, alignment);
    812 	if (usize == 0)
    813 		return (NULL);
    814 	p = ipalloct(usize, alignment, zero, try_tcache_alloc, arena);
    815 	if (p == NULL) {
    816 		if (extra == 0)
    817 			return (NULL);
    818 		/* Try again, without extra this time. */
    819 		usize = sa2u(size, alignment);
    820 		if (usize == 0)
    821 			return (NULL);
    822 		p = ipalloct(usize, alignment, zero, try_tcache_alloc, arena);
    823 		if (p == NULL)
    824 			return (NULL);
    825 	}
    826 	/*
    827 	 * Copy at most size bytes (not size+extra), since the caller has no
    828 	 * expectation that the extra bytes will be reliably preserved.
    829 	 */
    830 	copysize = (size < oldsize) ? size : oldsize;
    831 	memcpy(p, ptr, copysize);
    832 	iqalloct(ptr, try_tcache_dalloc);
    833 	return (p);
    834 }
    835 
    836 JEMALLOC_ALWAYS_INLINE void *
    837 iralloct(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
    838     bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena)
    839 {
    840 	size_t oldsize;
    841 
    842 	assert(ptr != NULL);
    843 	assert(size != 0);
    844 
    845 	oldsize = isalloc(ptr, config_prof);
    846 
    847 	if (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))
    848 	    != 0) {
    849 		/*
    850 		 * Existing object alignment is inadequate; allocate new space
    851 		 * and copy.
    852 		 */
    853 		return (iralloct_realign(ptr, oldsize, size, extra, alignment,
    854 		    zero, try_tcache_alloc, try_tcache_dalloc, arena));
    855 	}
    856 
    857 	if (size + extra <= arena_maxclass) {
    858 		return (arena_ralloc(arena, ptr, oldsize, size, extra,
    859 		    alignment, zero, try_tcache_alloc,
    860 		    try_tcache_dalloc));
    861 	} else {
    862 		return (huge_ralloc(arena, ptr, oldsize, size, extra,
    863 		    alignment, zero, try_tcache_dalloc));
    864 	}
    865 }
    866 
    867 JEMALLOC_ALWAYS_INLINE void *
    868 iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero)
    869 {
    870 
    871 	return (iralloct(ptr, size, extra, alignment, zero, true, true, NULL));
    872 }
    873 
    874 JEMALLOC_ALWAYS_INLINE bool
    875 ixalloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero)
    876 {
    877 	size_t oldsize;
    878 
    879 	assert(ptr != NULL);
    880 	assert(size != 0);
    881 
    882 	oldsize = isalloc(ptr, config_prof);
    883 	if (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))
    884 	    != 0) {
    885 		/* Existing object alignment is inadequate. */
    886 		return (true);
    887 	}
    888 
    889 	if (size <= arena_maxclass)
    890 		return (arena_ralloc_no_move(ptr, oldsize, size, extra, zero));
    891 	else
    892 		return (huge_ralloc_no_move(ptr, oldsize, size, extra));
    893 }
    894 
    895 malloc_tsd_externs(thread_allocated, thread_allocated_t)
    896 malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, thread_allocated, thread_allocated_t,
    897     THREAD_ALLOCATED_INITIALIZER, malloc_tsd_no_cleanup)
    898 #endif
    899 
    900 #include "jemalloc/internal/prof.h"
    901 
    902 #undef JEMALLOC_H_INLINES
    903 /******************************************************************************/
    904 #endif /* JEMALLOC_INTERNAL_H */
    905