1 1.1 christos #ifndef JEMALLOC_INTERNAL_EXTENT_H 2 1.1 christos #define JEMALLOC_INTERNAL_EXTENT_H 3 1.1 christos 4 1.1 christos #include "jemalloc/internal/ecache.h" 5 1.1 christos #include "jemalloc/internal/ehooks.h" 6 1.1 christos #include "jemalloc/internal/ph.h" 7 1.1 christos #include "jemalloc/internal/rtree.h" 8 1.1 christos 9 1.1 christos /* 10 1.1 christos * This module contains the page-level allocator. It chooses the addresses that 11 1.1 christos * allocations requested by other modules will inhabit, and updates the global 12 1.1 christos * metadata to reflect allocation/deallocation/purging decisions. 13 1.1 christos */ 14 1.1 christos 15 1.1 christos /* 16 1.1 christos * When reuse (and split) an active extent, (1U << opt_lg_extent_max_active_fit) 17 1.1 christos * is the max ratio between the size of the active extent and the new extent. 18 1.1 christos */ 19 1.1 christos #define LG_EXTENT_MAX_ACTIVE_FIT_DEFAULT 6 20 1.1 christos extern size_t opt_lg_extent_max_active_fit; 21 1.1 christos 22 1.1 christos edata_t *ecache_alloc(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, 23 1.1 christos ecache_t *ecache, edata_t *expand_edata, size_t size, size_t alignment, 24 1.1 christos bool zero, bool guarded); 25 1.1 christos edata_t *ecache_alloc_grow(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, 26 1.1 christos ecache_t *ecache, edata_t *expand_edata, size_t size, size_t alignment, 27 1.1 christos bool zero, bool guarded); 28 1.1 christos void ecache_dalloc(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, 29 1.1 christos ecache_t *ecache, edata_t *edata); 30 1.1 christos edata_t *ecache_evict(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, 31 1.1 christos ecache_t *ecache, size_t npages_min); 32 1.1 christos 33 1.1 christos void extent_gdump_add(tsdn_t *tsdn, const edata_t *edata); 34 1.1 christos void extent_record(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, ecache_t *ecache, 35 1.1 christos edata_t *edata); 36 1.1 christos void extent_dalloc_gap(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, 37 1.1 christos edata_t *edata); 38 1.1 christos edata_t *extent_alloc_wrapper(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, 39 1.1 christos void *new_addr, size_t size, size_t alignment, bool zero, bool *commit, 40 1.1 christos bool growing_retained); 41 1.1 christos void extent_dalloc_wrapper(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, 42 1.1 christos edata_t *edata); 43 1.1 christos void extent_destroy_wrapper(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, 44 1.1 christos edata_t *edata); 45 1.1 christos bool extent_commit_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, 46 1.1 christos size_t offset, size_t length); 47 1.1 christos bool extent_decommit_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, 48 1.1 christos size_t offset, size_t length); 49 1.1 christos bool extent_purge_lazy_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, 50 1.1 christos size_t offset, size_t length); 51 1.1 christos bool extent_purge_forced_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, 52 1.1 christos size_t offset, size_t length); 53 1.1 christos edata_t *extent_split_wrapper(tsdn_t *tsdn, pac_t *pac, 54 1.1 christos ehooks_t *ehooks, edata_t *edata, size_t size_a, size_t size_b, 55 1.1 christos bool holding_core_locks); 56 1.1 christos bool extent_merge_wrapper(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, 57 1.1 christos edata_t *a, edata_t *b); 58 1.1 christos bool extent_commit_zero(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, 59 1.1 christos bool commit, bool zero, bool growing_retained); 60 1.1 christos size_t extent_sn_next(pac_t *pac); 61 1.1 christos bool extent_boot(void); 62 1.1 christos 63 1.1 christos JEMALLOC_ALWAYS_INLINE bool 64 1.1 christos extent_neighbor_head_state_mergeable(bool edata_is_head, 65 1.1 christos bool neighbor_is_head, bool forward) { 66 1.1 christos /* 67 1.1 christos * Head states checking: disallow merging if the higher addr extent is a 68 1.1 christos * head extent. This helps preserve first-fit, and more importantly 69 1.1 christos * makes sure no merge across arenas. 70 1.1 christos */ 71 1.1 christos if (forward) { 72 1.1 christos if (neighbor_is_head) { 73 1.1 christos return false; 74 1.1 christos } 75 1.1 christos } else { 76 1.1 christos if (edata_is_head) { 77 1.1 christos return false; 78 1.1 christos } 79 1.1 christos } 80 1.1 christos return true; 81 1.1 christos } 82 1.1 christos 83 1.1 christos JEMALLOC_ALWAYS_INLINE bool 84 1.1 christos extent_can_acquire_neighbor(edata_t *edata, rtree_contents_t contents, 85 1.1 christos extent_pai_t pai, extent_state_t expected_state, bool forward, 86 1.1 christos bool expanding) { 87 1.1 christos edata_t *neighbor = contents.edata; 88 1.1 christos if (neighbor == NULL) { 89 1.1 christos return false; 90 1.1 christos } 91 1.1 christos /* It's not safe to access *neighbor yet; must verify states first. */ 92 1.1 christos bool neighbor_is_head = contents.metadata.is_head; 93 1.1 christos if (!extent_neighbor_head_state_mergeable(edata_is_head_get(edata), 94 1.1 christos neighbor_is_head, forward)) { 95 1.1 christos return false; 96 1.1 christos } 97 1.1 christos extent_state_t neighbor_state = contents.metadata.state; 98 1.1 christos if (pai == EXTENT_PAI_PAC) { 99 1.1 christos if (neighbor_state != expected_state) { 100 1.1 christos return false; 101 1.1 christos } 102 1.1 christos /* From this point, it's safe to access *neighbor. */ 103 1.1 christos if (!expanding && (edata_committed_get(edata) != 104 1.1 christos edata_committed_get(neighbor))) { 105 1.1 christos /* 106 1.1 christos * Some platforms (e.g. Windows) require an explicit 107 1.1 christos * commit step (and writing to uncommitted memory is not 108 1.1 christos * allowed). 109 1.1 christos */ 110 1.1 christos return false; 111 1.1 christos } 112 1.1 christos } else { 113 1.1 christos if (neighbor_state == extent_state_active) { 114 1.1 christos return false; 115 1.1 christos } 116 1.1 christos /* From this point, it's safe to access *neighbor. */ 117 1.1 christos } 118 1.1 christos 119 1.1 christos assert(edata_pai_get(edata) == pai); 120 1.1 christos if (edata_pai_get(neighbor) != pai) { 121 1.1 christos return false; 122 1.1 christos } 123 1.1 christos if (opt_retain) { 124 1.1 christos assert(edata_arena_ind_get(edata) == 125 1.1 christos edata_arena_ind_get(neighbor)); 126 1.1 christos } else { 127 1.1 christos if (edata_arena_ind_get(edata) != 128 1.1 christos edata_arena_ind_get(neighbor)) { 129 1.1 christos return false; 130 1.1 christos } 131 1.1 christos } 132 1.1 christos assert(!edata_guarded_get(edata) && !edata_guarded_get(neighbor)); 133 1.1 christos 134 1.1 christos return true; 135 1.1 christos } 136 1.1 christos 137 1.1 christos #endif /* JEMALLOC_INTERNAL_EXTENT_H */ 138