Home | History | Annotate | Line # | Download | only in internal
      1 #ifndef JEMALLOC_INTERNAL_EDATA_H
      2 #define JEMALLOC_INTERNAL_EDATA_H
      3 
      4 #include "jemalloc/internal/atomic.h"
      5 #include "jemalloc/internal/bin_info.h"
      6 #include "jemalloc/internal/bit_util.h"
      7 #include "jemalloc/internal/hpdata.h"
      8 #include "jemalloc/internal/nstime.h"
      9 #include "jemalloc/internal/ph.h"
     10 #include "jemalloc/internal/ql.h"
     11 #include "jemalloc/internal/sc.h"
     12 #include "jemalloc/internal/slab_data.h"
     13 #include "jemalloc/internal/sz.h"
     14 #include "jemalloc/internal/typed_list.h"
     15 
     16 /*
     17  * sizeof(edata_t) is 128 bytes on 64-bit architectures.  Ensure the alignment
     18  * to free up the low bits in the rtree leaf.
     19  */
     20 #define EDATA_ALIGNMENT 128
     21 
     22 enum extent_state_e {
     23 	extent_state_active   = 0,
     24 	extent_state_dirty    = 1,
     25 	extent_state_muzzy    = 2,
     26 	extent_state_retained = 3,
     27 	extent_state_transition = 4, /* States below are intermediate. */
     28 	extent_state_merging = 5,
     29 	extent_state_max = 5 /* Sanity checking only. */
     30 };
     31 typedef enum extent_state_e extent_state_t;
     32 
     33 enum extent_head_state_e {
     34 	EXTENT_NOT_HEAD,
     35 	EXTENT_IS_HEAD   /* See comments in ehooks_default_merge_impl(). */
     36 };
     37 typedef enum extent_head_state_e extent_head_state_t;
     38 
     39 /*
     40  * Which implementation of the page allocator interface, (PAI, defined in
     41  * pai.h) owns the given extent?
     42  */
     43 enum extent_pai_e {
     44 	EXTENT_PAI_PAC = 0,
     45 	EXTENT_PAI_HPA = 1
     46 };
     47 typedef enum extent_pai_e extent_pai_t;
     48 
     49 struct e_prof_info_s {
     50 	/* Time when this was allocated. */
     51 	nstime_t	e_prof_alloc_time;
     52 	/* Allocation request size. */
     53 	size_t		e_prof_alloc_size;
     54 	/* Points to a prof_tctx_t. */
     55 	atomic_p_t	e_prof_tctx;
     56 	/*
     57 	 * Points to a prof_recent_t for the allocation; NULL
     58 	 * means the recent allocation record no longer exists.
     59 	 * Protected by prof_recent_alloc_mtx.
     60 	 */
     61 	atomic_p_t	e_prof_recent_alloc;
     62 };
     63 typedef struct e_prof_info_s e_prof_info_t;
     64 
     65 /*
     66  * The information about a particular edata that lives in an emap.  Space is
     67  * more precious there (the information, plus the edata pointer, has to live in
     68  * a 64-bit word if we want to enable a packed representation.
     69  *
     70  * There are two things that are special about the information here:
     71  * - It's quicker to access.  You have one fewer pointer hop, since finding the
     72  *   edata_t associated with an item always requires accessing the rtree leaf in
     73  *   which this data is stored.
     74  * - It can be read unsynchronized, and without worrying about lifetime issues.
     75  */
     76 typedef struct edata_map_info_s edata_map_info_t;
     77 struct edata_map_info_s {
     78 	bool slab;
     79 	szind_t szind;
     80 };
     81 
     82 typedef struct edata_cmp_summary_s edata_cmp_summary_t;
     83 struct edata_cmp_summary_s {
     84 	uint64_t sn;
     85 	uintptr_t addr;
     86 };
     87 
     88 /* Extent (span of pages).  Use accessor functions for e_* fields. */
     89 typedef struct edata_s edata_t;
     90 ph_structs(edata_avail, edata_t);
     91 ph_structs(edata_heap, edata_t);
     92 struct edata_s {
     93 	/*
     94 	 * Bitfield containing several fields:
     95 	 *
     96 	 * a: arena_ind
     97 	 * b: slab
     98 	 * c: committed
     99 	 * p: pai
    100 	 * z: zeroed
    101 	 * g: guarded
    102 	 * t: state
    103 	 * i: szind
    104 	 * f: nfree
    105 	 * s: bin_shard
    106 	 *
    107 	 * 00000000 ... 0000ssss ssffffff ffffiiii iiiitttg zpcbaaaa aaaaaaaa
    108 	 *
    109 	 * arena_ind: Arena from which this extent came, or all 1 bits if
    110 	 *            unassociated.
    111 	 *
    112 	 * slab: The slab flag indicates whether the extent is used for a slab
    113 	 *       of small regions.  This helps differentiate small size classes,
    114 	 *       and it indicates whether interior pointers can be looked up via
    115 	 *       iealloc().
    116 	 *
    117 	 * committed: The committed flag indicates whether physical memory is
    118 	 *            committed to the extent, whether explicitly or implicitly
    119 	 *            as on a system that overcommits and satisfies physical
    120 	 *            memory needs on demand via soft page faults.
    121 	 *
    122 	 * pai: The pai flag is an extent_pai_t.
    123 	 *
    124 	 * zeroed: The zeroed flag is used by extent recycling code to track
    125 	 *         whether memory is zero-filled.
    126 	 *
    127 	 * guarded: The guarded flag is use by the sanitizer to track whether
    128 	 *          the extent has page guards around it.
    129 	 *
    130 	 * state: The state flag is an extent_state_t.
    131 	 *
    132 	 * szind: The szind flag indicates usable size class index for
    133 	 *        allocations residing in this extent, regardless of whether the
    134 	 *        extent is a slab.  Extent size and usable size often differ
    135 	 *        even for non-slabs, either due to sz_large_pad or promotion of
    136 	 *        sampled small regions.
    137 	 *
    138 	 * nfree: Number of free regions in slab.
    139 	 *
    140 	 * bin_shard: the shard of the bin from which this extent came.
    141 	 */
    142 	uint64_t		e_bits;
    143 #define MASK(CURRENT_FIELD_WIDTH, CURRENT_FIELD_SHIFT) ((((((uint64_t)0x1U) << (CURRENT_FIELD_WIDTH)) - 1)) << (CURRENT_FIELD_SHIFT))
    144 
    145 #define EDATA_BITS_ARENA_WIDTH  MALLOCX_ARENA_BITS
    146 #define EDATA_BITS_ARENA_SHIFT  0
    147 #define EDATA_BITS_ARENA_MASK  MASK(EDATA_BITS_ARENA_WIDTH, EDATA_BITS_ARENA_SHIFT)
    148 
    149 #define EDATA_BITS_SLAB_WIDTH  1
    150 #define EDATA_BITS_SLAB_SHIFT  (EDATA_BITS_ARENA_WIDTH + EDATA_BITS_ARENA_SHIFT)
    151 #define EDATA_BITS_SLAB_MASK  MASK(EDATA_BITS_SLAB_WIDTH, EDATA_BITS_SLAB_SHIFT)
    152 
    153 #define EDATA_BITS_COMMITTED_WIDTH  1
    154 #define EDATA_BITS_COMMITTED_SHIFT  (EDATA_BITS_SLAB_WIDTH + EDATA_BITS_SLAB_SHIFT)
    155 #define EDATA_BITS_COMMITTED_MASK  MASK(EDATA_BITS_COMMITTED_WIDTH, EDATA_BITS_COMMITTED_SHIFT)
    156 
    157 #define EDATA_BITS_PAI_WIDTH  1
    158 #define EDATA_BITS_PAI_SHIFT  (EDATA_BITS_COMMITTED_WIDTH + EDATA_BITS_COMMITTED_SHIFT)
    159 #define EDATA_BITS_PAI_MASK  MASK(EDATA_BITS_PAI_WIDTH, EDATA_BITS_PAI_SHIFT)
    160 
    161 #define EDATA_BITS_ZEROED_WIDTH  1
    162 #define EDATA_BITS_ZEROED_SHIFT  (EDATA_BITS_PAI_WIDTH + EDATA_BITS_PAI_SHIFT)
    163 #define EDATA_BITS_ZEROED_MASK  MASK(EDATA_BITS_ZEROED_WIDTH, EDATA_BITS_ZEROED_SHIFT)
    164 
    165 #define EDATA_BITS_GUARDED_WIDTH  1
    166 #define EDATA_BITS_GUARDED_SHIFT  (EDATA_BITS_ZEROED_WIDTH + EDATA_BITS_ZEROED_SHIFT)
    167 #define EDATA_BITS_GUARDED_MASK  MASK(EDATA_BITS_GUARDED_WIDTH, EDATA_BITS_GUARDED_SHIFT)
    168 
    169 #define EDATA_BITS_STATE_WIDTH  3
    170 #define EDATA_BITS_STATE_SHIFT  (EDATA_BITS_GUARDED_WIDTH + EDATA_BITS_GUARDED_SHIFT)
    171 #define EDATA_BITS_STATE_MASK  MASK(EDATA_BITS_STATE_WIDTH, EDATA_BITS_STATE_SHIFT)
    172 
    173 #define EDATA_BITS_SZIND_WIDTH  LG_CEIL(SC_NSIZES)
    174 #define EDATA_BITS_SZIND_SHIFT  (EDATA_BITS_STATE_WIDTH + EDATA_BITS_STATE_SHIFT)
    175 #define EDATA_BITS_SZIND_MASK  MASK(EDATA_BITS_SZIND_WIDTH, EDATA_BITS_SZIND_SHIFT)
    176 
    177 #define EDATA_BITS_NFREE_WIDTH  (SC_LG_SLAB_MAXREGS + 1)
    178 #define EDATA_BITS_NFREE_SHIFT  (EDATA_BITS_SZIND_WIDTH + EDATA_BITS_SZIND_SHIFT)
    179 #define EDATA_BITS_NFREE_MASK  MASK(EDATA_BITS_NFREE_WIDTH, EDATA_BITS_NFREE_SHIFT)
    180 
    181 #define EDATA_BITS_BINSHARD_WIDTH  6
    182 #define EDATA_BITS_BINSHARD_SHIFT  (EDATA_BITS_NFREE_WIDTH + EDATA_BITS_NFREE_SHIFT)
    183 #define EDATA_BITS_BINSHARD_MASK  MASK(EDATA_BITS_BINSHARD_WIDTH, EDATA_BITS_BINSHARD_SHIFT)
    184 
    185 #define EDATA_BITS_IS_HEAD_WIDTH 1
    186 #define EDATA_BITS_IS_HEAD_SHIFT  (EDATA_BITS_BINSHARD_WIDTH + EDATA_BITS_BINSHARD_SHIFT)
    187 #define EDATA_BITS_IS_HEAD_MASK  MASK(EDATA_BITS_IS_HEAD_WIDTH, EDATA_BITS_IS_HEAD_SHIFT)
    188 
    189 	/* Pointer to the extent that this structure is responsible for. */
    190 	void			*e_addr;
    191 
    192 	union {
    193 		/*
    194 		 * Extent size and serial number associated with the extent
    195 		 * structure (different than the serial number for the extent at
    196 		 * e_addr).
    197 		 *
    198 		 * ssssssss [...] ssssssss ssssnnnn nnnnnnnn
    199 		 */
    200 		size_t			e_size_esn;
    201 	#define EDATA_SIZE_MASK	((size_t)~(PAGE-1))
    202 	#define EDATA_ESN_MASK		((size_t)PAGE-1)
    203 		/* Base extent size, which may not be a multiple of PAGE. */
    204 		size_t			e_bsize;
    205 	};
    206 
    207 	/*
    208 	 * If this edata is a user allocation from an HPA, it comes out of some
    209 	 * pageslab (we don't yet support huegpage allocations that don't fit
    210 	 * into pageslabs).  This tracks it.
    211 	 */
    212 	hpdata_t *e_ps;
    213 
    214 	/*
    215 	 * Serial number.  These are not necessarily unique; splitting an extent
    216 	 * results in two extents with the same serial number.
    217 	 */
    218 	uint64_t e_sn;
    219 
    220 	union {
    221 		/*
    222 		 * List linkage used when the edata_t is active; either in
    223 		 * arena's large allocations or bin_t's slabs_full.
    224 		 */
    225 		ql_elm(edata_t)	ql_link_active;
    226 		/*
    227 		 * Pairing heap linkage.  Used whenever the extent is inactive
    228 		 * (in the page allocators), or when it is active and in
    229 		 * slabs_nonfull, or when the edata_t is unassociated with an
    230 		 * extent and sitting in an edata_cache.
    231 		 */
    232 		union {
    233 			edata_heap_link_t heap_link;
    234 			edata_avail_link_t avail_link;
    235 		};
    236 	};
    237 
    238 	union {
    239 		/*
    240 		 * List linkage used when the extent is inactive:
    241 		 * - Stashed dirty extents
    242 		 * - Ecache LRU functionality.
    243 		 */
    244 		ql_elm(edata_t) ql_link_inactive;
    245 		/* Small region slab metadata. */
    246 		slab_data_t	e_slab_data;
    247 
    248 		/* Profiling data, used for large objects. */
    249 		e_prof_info_t	e_prof_info;
    250 	};
    251 };
    252 
    253 TYPED_LIST(edata_list_active, edata_t, ql_link_active)
    254 TYPED_LIST(edata_list_inactive, edata_t, ql_link_inactive)
    255 
    256 static inline unsigned
    257 edata_arena_ind_get(const edata_t *edata) {
    258 	unsigned arena_ind = (unsigned)((edata->e_bits &
    259 	    EDATA_BITS_ARENA_MASK) >> EDATA_BITS_ARENA_SHIFT);
    260 	assert(arena_ind < MALLOCX_ARENA_LIMIT);
    261 
    262 	return arena_ind;
    263 }
    264 
    265 static inline szind_t
    266 edata_szind_get_maybe_invalid(const edata_t *edata) {
    267 	szind_t szind = (szind_t)((edata->e_bits & EDATA_BITS_SZIND_MASK) >>
    268 	    EDATA_BITS_SZIND_SHIFT);
    269 	assert(szind <= SC_NSIZES);
    270 	return szind;
    271 }
    272 
    273 static inline szind_t
    274 edata_szind_get(const edata_t *edata) {
    275 	szind_t szind = edata_szind_get_maybe_invalid(edata);
    276 	assert(szind < SC_NSIZES); /* Never call when "invalid". */
    277 	return szind;
    278 }
    279 
    280 static inline size_t
    281 edata_usize_get(const edata_t *edata) {
    282 	return sz_index2size(edata_szind_get(edata));
    283 }
    284 
    285 static inline unsigned
    286 edata_binshard_get(const edata_t *edata) {
    287 	unsigned binshard = (unsigned)((edata->e_bits &
    288 	    EDATA_BITS_BINSHARD_MASK) >> EDATA_BITS_BINSHARD_SHIFT);
    289 	assert(binshard < bin_infos[edata_szind_get(edata)].n_shards);
    290 	return binshard;
    291 }
    292 
    293 static inline uint64_t
    294 edata_sn_get(const edata_t *edata) {
    295 	return edata->e_sn;
    296 }
    297 
    298 static inline extent_state_t
    299 edata_state_get(const edata_t *edata) {
    300 	return (extent_state_t)((edata->e_bits & EDATA_BITS_STATE_MASK) >>
    301 	    EDATA_BITS_STATE_SHIFT);
    302 }
    303 
    304 static inline bool
    305 edata_guarded_get(const edata_t *edata) {
    306 	return (bool)((edata->e_bits & EDATA_BITS_GUARDED_MASK) >>
    307 	    EDATA_BITS_GUARDED_SHIFT);
    308 }
    309 
    310 static inline bool
    311 edata_zeroed_get(const edata_t *edata) {
    312 	return (bool)((edata->e_bits & EDATA_BITS_ZEROED_MASK) >>
    313 	    EDATA_BITS_ZEROED_SHIFT);
    314 }
    315 
    316 static inline bool
    317 edata_committed_get(const edata_t *edata) {
    318 	return (bool)((edata->e_bits & EDATA_BITS_COMMITTED_MASK) >>
    319 	    EDATA_BITS_COMMITTED_SHIFT);
    320 }
    321 
    322 static inline extent_pai_t
    323 edata_pai_get(const edata_t *edata) {
    324 	return (extent_pai_t)((edata->e_bits & EDATA_BITS_PAI_MASK) >>
    325 	    EDATA_BITS_PAI_SHIFT);
    326 }
    327 
    328 static inline bool
    329 edata_slab_get(const edata_t *edata) {
    330 	return (bool)((edata->e_bits & EDATA_BITS_SLAB_MASK) >>
    331 	    EDATA_BITS_SLAB_SHIFT);
    332 }
    333 
    334 static inline unsigned
    335 edata_nfree_get(const edata_t *edata) {
    336 	assert(edata_slab_get(edata));
    337 	return (unsigned)((edata->e_bits & EDATA_BITS_NFREE_MASK) >>
    338 	    EDATA_BITS_NFREE_SHIFT);
    339 }
    340 
    341 static inline void *
    342 edata_base_get(const edata_t *edata) {
    343 	assert(edata->e_addr == PAGE_ADDR2BASE(edata->e_addr) ||
    344 	    !edata_slab_get(edata));
    345 	return PAGE_ADDR2BASE(edata->e_addr);
    346 }
    347 
    348 static inline void *
    349 edata_addr_get(const edata_t *edata) {
    350 	assert(edata->e_addr == PAGE_ADDR2BASE(edata->e_addr) ||
    351 	    !edata_slab_get(edata));
    352 	return edata->e_addr;
    353 }
    354 
    355 static inline size_t
    356 edata_size_get(const edata_t *edata) {
    357 	return (edata->e_size_esn & EDATA_SIZE_MASK);
    358 }
    359 
    360 static inline size_t
    361 edata_esn_get(const edata_t *edata) {
    362 	return (edata->e_size_esn & EDATA_ESN_MASK);
    363 }
    364 
    365 static inline size_t
    366 edata_bsize_get(const edata_t *edata) {
    367 	return edata->e_bsize;
    368 }
    369 
    370 static inline hpdata_t *
    371 edata_ps_get(const edata_t *edata) {
    372 	assert(edata_pai_get(edata) == EXTENT_PAI_HPA);
    373 	return edata->e_ps;
    374 }
    375 
    376 static inline void *
    377 edata_before_get(const edata_t *edata) {
    378 	return (void *)((uintptr_t)edata_base_get(edata) - PAGE);
    379 }
    380 
    381 static inline void *
    382 edata_last_get(const edata_t *edata) {
    383 	return (void *)((uintptr_t)edata_base_get(edata) +
    384 	    edata_size_get(edata) - PAGE);
    385 }
    386 
    387 static inline void *
    388 edata_past_get(const edata_t *edata) {
    389 	return (void *)((uintptr_t)edata_base_get(edata) +
    390 	    edata_size_get(edata));
    391 }
    392 
    393 static inline slab_data_t *
    394 edata_slab_data_get(edata_t *edata) {
    395 	assert(edata_slab_get(edata));
    396 	return &edata->e_slab_data;
    397 }
    398 
    399 static inline const slab_data_t *
    400 edata_slab_data_get_const(const edata_t *edata) {
    401 	assert(edata_slab_get(edata));
    402 	return &edata->e_slab_data;
    403 }
    404 
    405 static inline prof_tctx_t *
    406 edata_prof_tctx_get(const edata_t *edata) {
    407 	return (prof_tctx_t *)atomic_load_p(&edata->e_prof_info.e_prof_tctx,
    408 	    ATOMIC_ACQUIRE);
    409 }
    410 
    411 static inline const nstime_t *
    412 edata_prof_alloc_time_get(const edata_t *edata) {
    413 	return &edata->e_prof_info.e_prof_alloc_time;
    414 }
    415 
    416 static inline size_t
    417 edata_prof_alloc_size_get(const edata_t *edata) {
    418 	return edata->e_prof_info.e_prof_alloc_size;
    419 }
    420 
    421 static inline prof_recent_t *
    422 edata_prof_recent_alloc_get_dont_call_directly(const edata_t *edata) {
    423 	return (prof_recent_t *)atomic_load_p(
    424 	    &edata->e_prof_info.e_prof_recent_alloc, ATOMIC_RELAXED);
    425 }
    426 
    427 static inline void
    428 edata_arena_ind_set(edata_t *edata, unsigned arena_ind) {
    429 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_ARENA_MASK) |
    430 	    ((uint64_t)arena_ind << EDATA_BITS_ARENA_SHIFT);
    431 }
    432 
    433 static inline void
    434 edata_binshard_set(edata_t *edata, unsigned binshard) {
    435 	/* The assertion assumes szind is set already. */
    436 	assert(binshard < bin_infos[edata_szind_get(edata)].n_shards);
    437 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_BINSHARD_MASK) |
    438 	    ((uint64_t)binshard << EDATA_BITS_BINSHARD_SHIFT);
    439 }
    440 
    441 static inline void
    442 edata_addr_set(edata_t *edata, void *addr) {
    443 	edata->e_addr = addr;
    444 }
    445 
    446 static inline void
    447 edata_size_set(edata_t *edata, size_t size) {
    448 	assert((size & ~EDATA_SIZE_MASK) == 0);
    449 	edata->e_size_esn = size | (edata->e_size_esn & ~EDATA_SIZE_MASK);
    450 }
    451 
    452 static inline void
    453 edata_esn_set(edata_t *edata, size_t esn) {
    454 	edata->e_size_esn = (edata->e_size_esn & ~EDATA_ESN_MASK) | (esn &
    455 	    EDATA_ESN_MASK);
    456 }
    457 
    458 static inline void
    459 edata_bsize_set(edata_t *edata, size_t bsize) {
    460 	edata->e_bsize = bsize;
    461 }
    462 
    463 static inline void
    464 edata_ps_set(edata_t *edata, hpdata_t *ps) {
    465 	assert(edata_pai_get(edata) == EXTENT_PAI_HPA);
    466 	edata->e_ps = ps;
    467 }
    468 
    469 static inline void
    470 edata_szind_set(edata_t *edata, szind_t szind) {
    471 	assert(szind <= SC_NSIZES); /* SC_NSIZES means "invalid". */
    472 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_SZIND_MASK) |
    473 	    ((uint64_t)szind << EDATA_BITS_SZIND_SHIFT);
    474 }
    475 
    476 static inline void
    477 edata_nfree_set(edata_t *edata, unsigned nfree) {
    478 	assert(edata_slab_get(edata));
    479 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_NFREE_MASK) |
    480 	    ((uint64_t)nfree << EDATA_BITS_NFREE_SHIFT);
    481 }
    482 
    483 static inline void
    484 edata_nfree_binshard_set(edata_t *edata, unsigned nfree, unsigned binshard) {
    485 	/* The assertion assumes szind is set already. */
    486 	assert(binshard < bin_infos[edata_szind_get(edata)].n_shards);
    487 	edata->e_bits = (edata->e_bits &
    488 	    (~EDATA_BITS_NFREE_MASK & ~EDATA_BITS_BINSHARD_MASK)) |
    489 	    ((uint64_t)binshard << EDATA_BITS_BINSHARD_SHIFT) |
    490 	    ((uint64_t)nfree << EDATA_BITS_NFREE_SHIFT);
    491 }
    492 
    493 static inline void
    494 edata_nfree_inc(edata_t *edata) {
    495 	assert(edata_slab_get(edata));
    496 	edata->e_bits += ((uint64_t)1U << EDATA_BITS_NFREE_SHIFT);
    497 }
    498 
    499 static inline void
    500 edata_nfree_dec(edata_t *edata) {
    501 	assert(edata_slab_get(edata));
    502 	edata->e_bits -= ((uint64_t)1U << EDATA_BITS_NFREE_SHIFT);
    503 }
    504 
    505 static inline void
    506 edata_nfree_sub(edata_t *edata, uint64_t n) {
    507 	assert(edata_slab_get(edata));
    508 	edata->e_bits -= (n << EDATA_BITS_NFREE_SHIFT);
    509 }
    510 
    511 static inline void
    512 edata_sn_set(edata_t *edata, uint64_t sn) {
    513 	edata->e_sn = sn;
    514 }
    515 
    516 static inline void
    517 edata_state_set(edata_t *edata, extent_state_t state) {
    518 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_STATE_MASK) |
    519 	    ((uint64_t)state << EDATA_BITS_STATE_SHIFT);
    520 }
    521 
    522 static inline void
    523 edata_guarded_set(edata_t *edata, bool guarded) {
    524 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_GUARDED_MASK) |
    525 	    ((uint64_t)guarded << EDATA_BITS_GUARDED_SHIFT);
    526 }
    527 
    528 static inline void
    529 edata_zeroed_set(edata_t *edata, bool zeroed) {
    530 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_ZEROED_MASK) |
    531 	    ((uint64_t)zeroed << EDATA_BITS_ZEROED_SHIFT);
    532 }
    533 
    534 static inline void
    535 edata_committed_set(edata_t *edata, bool committed) {
    536 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_COMMITTED_MASK) |
    537 	    ((uint64_t)committed << EDATA_BITS_COMMITTED_SHIFT);
    538 }
    539 
    540 static inline void
    541 edata_pai_set(edata_t *edata, extent_pai_t pai) {
    542 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_PAI_MASK) |
    543 	    ((uint64_t)pai << EDATA_BITS_PAI_SHIFT);
    544 }
    545 
    546 static inline void
    547 edata_slab_set(edata_t *edata, bool slab) {
    548 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_SLAB_MASK) |
    549 	    ((uint64_t)slab << EDATA_BITS_SLAB_SHIFT);
    550 }
    551 
    552 static inline void
    553 edata_prof_tctx_set(edata_t *edata, prof_tctx_t *tctx) {
    554 	atomic_store_p(&edata->e_prof_info.e_prof_tctx, tctx, ATOMIC_RELEASE);
    555 }
    556 
    557 static inline void
    558 edata_prof_alloc_time_set(edata_t *edata, nstime_t *t) {
    559 	nstime_copy(&edata->e_prof_info.e_prof_alloc_time, t);
    560 }
    561 
    562 static inline void
    563 edata_prof_alloc_size_set(edata_t *edata, size_t size) {
    564 	edata->e_prof_info.e_prof_alloc_size = size;
    565 }
    566 
    567 static inline void
    568 edata_prof_recent_alloc_set_dont_call_directly(edata_t *edata,
    569     prof_recent_t *recent_alloc) {
    570 	atomic_store_p(&edata->e_prof_info.e_prof_recent_alloc, recent_alloc,
    571 	    ATOMIC_RELAXED);
    572 }
    573 
    574 static inline bool
    575 edata_is_head_get(edata_t *edata) {
    576 	return (bool)((edata->e_bits & EDATA_BITS_IS_HEAD_MASK) >>
    577 	    EDATA_BITS_IS_HEAD_SHIFT);
    578 }
    579 
    580 static inline void
    581 edata_is_head_set(edata_t *edata, bool is_head) {
    582 	edata->e_bits = (edata->e_bits & ~EDATA_BITS_IS_HEAD_MASK) |
    583 	    ((uint64_t)is_head << EDATA_BITS_IS_HEAD_SHIFT);
    584 }
    585 
    586 static inline bool
    587 edata_state_in_transition(extent_state_t state) {
    588 	return state >= extent_state_transition;
    589 }
    590 
    591 /*
    592  * Because this function is implemented as a sequence of bitfield modifications,
    593  * even though each individual bit is properly initialized, we technically read
    594  * uninitialized data within it.  This is mostly fine, since most callers get
    595  * their edatas from zeroing sources, but callers who make stack edata_ts need
    596  * to manually zero them.
    597  */
    598 static inline void
    599 edata_init(edata_t *edata, unsigned arena_ind, void *addr, size_t size,
    600     bool slab, szind_t szind, uint64_t sn, extent_state_t state, bool zeroed,
    601     bool committed, extent_pai_t pai, extent_head_state_t is_head) {
    602 	assert(addr == PAGE_ADDR2BASE(addr) || !slab);
    603 
    604 	edata_arena_ind_set(edata, arena_ind);
    605 	edata_addr_set(edata, addr);
    606 	edata_size_set(edata, size);
    607 	edata_slab_set(edata, slab);
    608 	edata_szind_set(edata, szind);
    609 	edata_sn_set(edata, sn);
    610 	edata_state_set(edata, state);
    611 	edata_guarded_set(edata, false);
    612 	edata_zeroed_set(edata, zeroed);
    613 	edata_committed_set(edata, committed);
    614 	edata_pai_set(edata, pai);
    615 	edata_is_head_set(edata, is_head == EXTENT_IS_HEAD);
    616 	if (config_prof) {
    617 		edata_prof_tctx_set(edata, NULL);
    618 	}
    619 }
    620 
    621 static inline void
    622 edata_binit(edata_t *edata, void *addr, size_t bsize, uint64_t sn) {
    623 	edata_arena_ind_set(edata, (1U << MALLOCX_ARENA_BITS) - 1);
    624 	edata_addr_set(edata, addr);
    625 	edata_bsize_set(edata, bsize);
    626 	edata_slab_set(edata, false);
    627 	edata_szind_set(edata, SC_NSIZES);
    628 	edata_sn_set(edata, sn);
    629 	edata_state_set(edata, extent_state_active);
    630 	edata_guarded_set(edata, false);
    631 	edata_zeroed_set(edata, true);
    632 	edata_committed_set(edata, true);
    633 	/*
    634 	 * This isn't strictly true, but base allocated extents never get
    635 	 * deallocated and can't be looked up in the emap, but no sense in
    636 	 * wasting a state bit to encode this fact.
    637 	 */
    638 	edata_pai_set(edata, EXTENT_PAI_PAC);
    639 }
    640 
    641 static inline int
    642 edata_esn_comp(const edata_t *a, const edata_t *b) {
    643 	size_t a_esn = edata_esn_get(a);
    644 	size_t b_esn = edata_esn_get(b);
    645 
    646 	return (a_esn > b_esn) - (a_esn < b_esn);
    647 }
    648 
    649 static inline int
    650 edata_ead_comp(const edata_t *a, const edata_t *b) {
    651 	uintptr_t a_eaddr = (uintptr_t)a;
    652 	uintptr_t b_eaddr = (uintptr_t)b;
    653 
    654 	return (a_eaddr > b_eaddr) - (a_eaddr < b_eaddr);
    655 }
    656 
    657 static inline edata_cmp_summary_t
    658 edata_cmp_summary_get(const edata_t *edata) {
    659 	return (edata_cmp_summary_t){edata_sn_get(edata),
    660 		(uintptr_t)edata_addr_get(edata)};
    661 }
    662 
    663 static inline int
    664 edata_cmp_summary_comp(edata_cmp_summary_t a, edata_cmp_summary_t b) {
    665 	int ret;
    666 	ret = (a.sn > b.sn) - (a.sn < b.sn);
    667 	if (ret != 0) {
    668 		return ret;
    669 	}
    670 	ret = (a.addr > b.addr) - (a.addr < b.addr);
    671 	return ret;
    672 }
    673 
    674 static inline int
    675 edata_snad_comp(const edata_t *a, const edata_t *b) {
    676 	edata_cmp_summary_t a_cmp = edata_cmp_summary_get(a);
    677 	edata_cmp_summary_t b_cmp = edata_cmp_summary_get(b);
    678 
    679 	return edata_cmp_summary_comp(a_cmp, b_cmp);
    680 }
    681 
    682 static inline int
    683 edata_esnead_comp(const edata_t *a, const edata_t *b) {
    684 	int ret;
    685 
    686 	ret = edata_esn_comp(a, b);
    687 	if (ret != 0) {
    688 		return ret;
    689 	}
    690 
    691 	ret = edata_ead_comp(a, b);
    692 	return ret;
    693 }
    694 
    695 ph_proto(, edata_avail, edata_t);
    696 ph_proto(, edata_heap, edata_t);
    697 
    698 #endif /* JEMALLOC_INTERNAL_EDATA_H */
    699