extent.h revision 1.1.1.1 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