]> git.proxmox.com Git - rustc.git/blame - src/jemalloc/src/base.c
New upstream version 1.22.1+dfsg1
[rustc.git] / src / jemalloc / src / base.c
CommitLineData
970d7e83
LB
1#define JEMALLOC_BASE_C_
2#include "jemalloc/internal/jemalloc_internal.h"
3
4/******************************************************************************/
5/* Data. */
6
7static malloc_mutex_t base_mtx;
3b2f2976
XL
8static size_t base_extent_sn_next;
9static extent_tree_t base_avail_szsnad;
970d7e83 10static extent_node_t *base_nodes;
54a0048b
SL
11static size_t base_allocated;
12static size_t base_resident;
13static size_t base_mapped;
970d7e83 14
970d7e83
LB
15/******************************************************************************/
16
54a0048b 17static extent_node_t *
3b2f2976 18base_node_try_alloc(tsdn_t *tsdn)
970d7e83 19{
54a0048b 20 extent_node_t *node;
970d7e83 21
3b2f2976
XL
22 malloc_mutex_assert_owner(tsdn, &base_mtx);
23
54a0048b
SL
24 if (base_nodes == NULL)
25 return (NULL);
26 node = base_nodes;
27 base_nodes = *(extent_node_t **)node;
28 JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t));
29 return (node);
970d7e83
LB
30}
31
54a0048b 32static void
3b2f2976 33base_node_dalloc(tsdn_t *tsdn, extent_node_t *node)
970d7e83 34{
970d7e83 35
3b2f2976
XL
36 malloc_mutex_assert_owner(tsdn, &base_mtx);
37
54a0048b
SL
38 JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t));
39 *(extent_node_t **)node = base_nodes;
40 base_nodes = node;
970d7e83
LB
41}
42
3b2f2976
XL
43static void
44base_extent_node_init(extent_node_t *node, void *addr, size_t size)
45{
46 size_t sn = atomic_add_z(&base_extent_sn_next, 1) - 1;
47
48 extent_node_init(node, NULL, addr, size, sn, true, true);
49}
50
54a0048b 51static extent_node_t *
3b2f2976 52base_chunk_alloc(tsdn_t *tsdn, size_t minsize)
970d7e83 53{
54a0048b
SL
54 extent_node_t *node;
55 size_t csize, nsize;
56 void *addr;
7453a54e 57
3b2f2976 58 malloc_mutex_assert_owner(tsdn, &base_mtx);
54a0048b 59 assert(minsize != 0);
3b2f2976 60 node = base_node_try_alloc(tsdn);
54a0048b
SL
61 /* Allocate enough space to also carve a node out if necessary. */
62 nsize = (node == NULL) ? CACHELINE_CEILING(sizeof(extent_node_t)) : 0;
63 csize = CHUNK_CEILING(minsize + nsize);
64 addr = chunk_alloc_base(csize);
65 if (addr == NULL) {
66 if (node != NULL)
3b2f2976 67 base_node_dalloc(tsdn, node);
54a0048b
SL
68 return (NULL);
69 }
70 base_mapped += csize;
71 if (node == NULL) {
72 node = (extent_node_t *)addr;
73 addr = (void *)((uintptr_t)addr + nsize);
74 csize -= nsize;
75 if (config_stats) {
76 base_allocated += nsize;
77 base_resident += PAGE_CEILING(nsize);
78 }
79 }
3b2f2976 80 base_extent_node_init(node, addr, csize);
54a0048b 81 return (node);
7453a54e
SL
82}
83
54a0048b
SL
84/*
85 * base_alloc() guarantees demand-zeroed memory, in order to make multi-page
86 * sparse data structures such as radix tree nodes efficient with respect to
87 * physical memory usage.
88 */
89void *
3b2f2976 90base_alloc(tsdn_t *tsdn, size_t size)
7453a54e 91{
54a0048b
SL
92 void *ret;
93 size_t csize, usize;
94 extent_node_t *node;
95 extent_node_t key;
96
97 /*
98 * Round size up to nearest multiple of the cacheline size, so that
99 * there is no chance of false cache line sharing.
100 */
101 csize = CACHELINE_CEILING(size);
970d7e83 102
54a0048b 103 usize = s2u(csize);
3b2f2976
XL
104 extent_node_init(&key, NULL, NULL, usize, 0, false, false);
105 malloc_mutex_lock(tsdn, &base_mtx);
106 node = extent_tree_szsnad_nsearch(&base_avail_szsnad, &key);
54a0048b
SL
107 if (node != NULL) {
108 /* Use existing space. */
3b2f2976 109 extent_tree_szsnad_remove(&base_avail_szsnad, node);
970d7e83 110 } else {
54a0048b 111 /* Try to allocate more space. */
3b2f2976 112 node = base_chunk_alloc(tsdn, csize);
54a0048b
SL
113 }
114 if (node == NULL) {
115 ret = NULL;
116 goto label_return;
970d7e83
LB
117 }
118
54a0048b
SL
119 ret = extent_node_addr_get(node);
120 if (extent_node_size_get(node) > csize) {
121 extent_node_addr_set(node, (void *)((uintptr_t)ret + csize));
122 extent_node_size_set(node, extent_node_size_get(node) - csize);
3b2f2976 123 extent_tree_szsnad_insert(&base_avail_szsnad, node);
54a0048b 124 } else
3b2f2976 125 base_node_dalloc(tsdn, node);
54a0048b
SL
126 if (config_stats) {
127 base_allocated += csize;
128 /*
129 * Add one PAGE to base_resident for every page boundary that is
130 * crossed by the new allocation.
131 */
132 base_resident += PAGE_CEILING((uintptr_t)ret + csize) -
133 PAGE_CEILING((uintptr_t)ret);
134 }
135 JEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ret, csize);
136label_return:
3b2f2976 137 malloc_mutex_unlock(tsdn, &base_mtx);
970d7e83
LB
138 return (ret);
139}
140
141void
3b2f2976
XL
142base_stats_get(tsdn_t *tsdn, size_t *allocated, size_t *resident,
143 size_t *mapped)
970d7e83
LB
144{
145
3b2f2976 146 malloc_mutex_lock(tsdn, &base_mtx);
54a0048b
SL
147 assert(base_allocated <= base_resident);
148 assert(base_resident <= base_mapped);
149 *allocated = base_allocated;
150 *resident = base_resident;
151 *mapped = base_mapped;
3b2f2976 152 malloc_mutex_unlock(tsdn, &base_mtx);
970d7e83
LB
153}
154
155bool
156base_boot(void)
157{
158
3b2f2976 159 if (malloc_mutex_init(&base_mtx, "base", WITNESS_RANK_BASE))
970d7e83 160 return (true);
3b2f2976
XL
161 base_extent_sn_next = 0;
162 extent_tree_szsnad_new(&base_avail_szsnad);
54a0048b 163 base_nodes = NULL;
970d7e83
LB
164
165 return (false);
166}
167
168void
3b2f2976 169base_prefork(tsdn_t *tsdn)
970d7e83
LB
170{
171
3b2f2976 172 malloc_mutex_prefork(tsdn, &base_mtx);
970d7e83
LB
173}
174
175void
3b2f2976 176base_postfork_parent(tsdn_t *tsdn)
970d7e83
LB
177{
178
3b2f2976 179 malloc_mutex_postfork_parent(tsdn, &base_mtx);
970d7e83
LB
180}
181
182void
3b2f2976 183base_postfork_child(tsdn_t *tsdn)
970d7e83
LB
184{
185
3b2f2976 186 malloc_mutex_postfork_child(tsdn, &base_mtx);
970d7e83 187}