#ifndef JEMALLOC_INTERNAL_EXTENT_STRUCTS_H #define JEMALLOC_INTERNAL_EXTENT_STRUCTS_H #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/ql.h" #include "jemalloc/internal/rb.h" #include "jemalloc/internal/ph.h" #include "jemalloc/internal/size_classes.h" typedef enum { extent_state_active = 0, extent_state_dirty = 1, extent_state_muzzy = 2, extent_state_retained = 3 } extent_state_t; /* Extent (span of pages). Use accessor functions for e_* fields. */ struct extent_s { /* * Bitfield containing several fields: * * a: arena_ind * b: slab * c: committed * z: zeroed * t: state * i: szind * f: nfree * n: sn * * nnnnnnnn ... nnnnnfff fffffffi iiiiiiit tzcbaaaa aaaaaaaa * * arena_ind: Arena from which this extent came, or all 1 bits if * unassociated. * * slab: The slab flag indicates whether the extent is used for a slab * of small regions. This helps differentiate small size classes, * and it indicates whether interior pointers can be looked up via * iealloc(). * * committed: The committed flag indicates whether physical memory is * committed to the extent, whether explicitly or implicitly * as on a system that overcommits and satisfies physical * memory needs on demand via soft page faults. * * zeroed: The zeroed flag is used by extent recycling code to track * whether memory is zero-filled. * * state: The state flag is an extent_state_t. * * szind: The szind flag indicates usable size class index for * allocations residing in this extent, regardless of whether the * extent is a slab. Extent size and usable size often differ * even for non-slabs, either due to large_pad or promotion of * sampled small regions. * * nfree: Number of free regions in slab. * * sn: Serial number (potentially non-unique). * * Serial numbers may wrap around if JEMALLOC_MUNMAP is defined, but * as long as comparison functions fall back on address comparison * for equal serial numbers, stable (if imperfect) ordering is * maintained. * * Serial numbers may not be unique even in the absence of * wrap-around, e.g. when splitting an extent and assigning the same * serial number to both resulting adjacent extents. */ uint64_t e_bits; #define EXTENT_BITS_ARENA_SHIFT 0 #define EXTENT_BITS_ARENA_MASK \ (((uint64_t)(1U << MALLOCX_ARENA_BITS) - 1) << EXTENT_BITS_ARENA_SHIFT) #define EXTENT_BITS_SLAB_SHIFT MALLOCX_ARENA_BITS #define EXTENT_BITS_SLAB_MASK \ ((uint64_t)0x1U << EXTENT_BITS_SLAB_SHIFT) #define EXTENT_BITS_COMMITTED_SHIFT (MALLOCX_ARENA_BITS + 1) #define EXTENT_BITS_COMMITTED_MASK \ ((uint64_t)0x1U << EXTENT_BITS_COMMITTED_SHIFT) #define EXTENT_BITS_ZEROED_SHIFT (MALLOCX_ARENA_BITS + 2) #define EXTENT_BITS_ZEROED_MASK \ ((uint64_t)0x1U << EXTENT_BITS_ZEROED_SHIFT) #define EXTENT_BITS_STATE_SHIFT (MALLOCX_ARENA_BITS + 3) #define EXTENT_BITS_STATE_MASK \ ((uint64_t)0x3U << EXTENT_BITS_STATE_SHIFT) #define EXTENT_BITS_SZIND_SHIFT (MALLOCX_ARENA_BITS + 5) #define EXTENT_BITS_SZIND_MASK \ (((uint64_t)(1U << LG_CEIL_NSIZES) - 1) << EXTENT_BITS_SZIND_SHIFT) #define EXTENT_BITS_NFREE_SHIFT \ (MALLOCX_ARENA_BITS + 5 + LG_CEIL_NSIZES) #define EXTENT_BITS_NFREE_MASK \ ((uint64_t)((1U << (LG_SLAB_MAXREGS + 1)) - 1) << EXTENT_BITS_NFREE_SHIFT) #define EXTENT_BITS_SN_SHIFT \ (MALLOCX_ARENA_BITS + 5 + LG_CEIL_NSIZES + (LG_SLAB_MAXREGS + 1)) #define EXTENT_BITS_SN_MASK (UINT64_MAX << EXTENT_BITS_SN_SHIFT) /* Pointer to the extent that this structure is responsible for. */ void *e_addr; union { /* * Extent size and serial number associated with the extent * structure (different than the serial number for the extent at * e_addr). * * ssssssss [...] ssssssss ssssnnnn nnnnnnnn */ size_t e_size_esn; #define EXTENT_SIZE_MASK ((size_t)~(PAGE-1)) #define EXTENT_ESN_MASK ((size_t)PAGE-1) /* Base extent size, which may not be a multiple of PAGE. */ size_t e_bsize; }; union { /* * List linkage, used by a variety of lists: * - arena_bin_t's slabs_full * - extents_t's LRU * - stashed dirty extents * - arena's large allocations */ ql_elm(extent_t) ql_link; /* Red-black tree linkage, used by arena's extent_avail. */ rb_node(extent_t) rb_link; }; /* Linkage for per size class sn/address-ordered heaps. */ phn(extent_t) ph_link; union { /* Small region slab metadata. */ arena_slab_data_t e_slab_data; /* * Profile counters, used for large objects. Points to a * prof_tctx_t. */ atomic_p_t e_prof_tctx; }; }; typedef ql_head(extent_t) extent_list_t; typedef rb_tree(extent_t) extent_tree_t; typedef ph(extent_t) extent_heap_t; /* Quantized collection of extents, with built-in LRU queue. */ struct extents_s { malloc_mutex_t mtx; /* * Quantized per size class heaps of extents. * * Synchronization: mtx. */ extent_heap_t heaps[NPSIZES+1]; /* * Bitmap for which set bits correspond to non-empty heaps. * * Synchronization: mtx. */ bitmap_t bitmap[BITMAP_GROUPS(NPSIZES+1)]; /* * LRU of all extents in heaps. * * Synchronization: mtx. */ extent_list_t lru; /* * Page sum for all extents in heaps. * * The synchronization here is a little tricky. Modifications to npages * must hold mtx, but reads need not (though, a reader who sees npages * without holding the mutex can't assume anything about the rest of the * state of the extents_t). */ atomic_zu_t npages; /* All stored extents must be in the same state. */ extent_state_t state; /* * If true, delay coalescing until eviction; otherwise coalesce during * deallocation. */ bool delay_coalesce; }; #endif /* JEMALLOC_INTERNAL_EXTENT_STRUCTS_H */