Home | History | Annotate | Line # | Download | only in internal
      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