@@ -177,13 +177,31 @@ mi_decl_cache_align _Atomic(mi_page_t**)* _mi_page_map;
177
177
static size_t mi_page_map_count ;
178
178
static void * mi_page_map_max_address ;
179
179
static mi_memid_t mi_page_map_memid ;
180
+
181
+ // divide the main map in 64 (`MI_BFIELD_BITS`) parts commit those parts on demand
180
182
static _Atomic (mi_bfield_t ) mi_page_map_commit ;
181
183
182
- static inline bool mi_page_map_is_committed (size_t idx , size_t * pbit_idx );
183
- static mi_page_t * * mi_page_map_ensure_committed (size_t idx );
184
- static mi_page_t * * mi_page_map_ensure_at (size_t idx );
185
- static inline void mi_page_map_set_range (mi_page_t * page , size_t idx , size_t sub_idx , size_t slice_count );
184
+ #define MI_PAGE_MAP_ENTRIES_PER_CBIT (MI_PAGE_MAP_COUNT / MI_BFIELD_BITS)
185
+
186
+ static inline bool mi_page_map_is_committed (size_t idx , size_t * pbit_idx ) {
187
+ mi_bfield_t commit = mi_atomic_load_relaxed (& mi_page_map_commit );
188
+ const size_t bit_idx = idx /MI_PAGE_MAP_ENTRIES_PER_CBIT ;
189
+ mi_assert_internal (bit_idx < MI_BFIELD_BITS );
190
+ if (pbit_idx != NULL ) { * pbit_idx = bit_idx ; }
191
+ return ((commit & (MI_ZU (1 ) << bit_idx )) != 0 );
192
+ }
193
+
194
+ static mi_page_t * * mi_page_map_ensure_committed (size_t idx ) {
195
+ size_t bit_idx ;
196
+ if mi_unlikely (!mi_page_map_is_committed (idx , & bit_idx )) {
197
+ uint8_t * start = (uint8_t * )& _mi_page_map [bit_idx * MI_PAGE_MAP_ENTRIES_PER_CBIT ];
198
+ _mi_os_commit (start , MI_PAGE_MAP_ENTRIES_PER_CBIT * sizeof (mi_page_t * * ), NULL );
199
+ mi_atomic_or_acq_rel (& mi_page_map_commit , MI_ZU (1 ) << bit_idx );
200
+ }
201
+ return mi_atomic_load_ptr_acquire (mi_page_t * , & _mi_page_map [idx ]); // _mi_page_map_at(idx);
202
+ }
186
203
204
+ // initialize the page map
187
205
bool _mi_page_map_init (void ) {
188
206
size_t vbits = (size_t )mi_option_get_clamp (mi_option_max_vabits , 0 , MI_SIZE_BITS );
189
207
if (vbits == 0 ) {
@@ -217,24 +235,24 @@ bool _mi_page_map_init(void) {
217
235
_mi_warning_message ("internal: the page map was committed but not zero initialized!\n" );
218
236
_mi_memzero_aligned (_mi_page_map , page_map_size );
219
237
}
220
- mi_atomic_store_release (& mi_page_map_commit , (commit ? ~MI_ZU (0 ) : MI_ZU (0 )));
238
+ mi_atomic_store_release (& mi_page_map_commit , (mi_page_map_memid . initially_committed ? ~MI_ZU (0 ) : MI_ZU (0 )));
221
239
222
- // note: for the NULL range we only commit one OS page (in the map and sub)
223
- if (!mi_page_map_memid .initially_committed ) {
224
- _mi_os_commit (& _mi_page_map [0 ], os_page_size , NULL ); // commit first part of the map
225
- }
226
- _mi_page_map [0 ] = (mi_page_t * * )((uint8_t * )_mi_page_map + page_map_size ); // we reserved a submap part at the end already
240
+ // ensure there is a submap for the NULL address
241
+ mi_page_t * * const sub0 = (mi_page_t * * )((uint8_t * )_mi_page_map + page_map_size ); // we reserved a submap part at the end already
227
242
if (!mi_page_map_memid .initially_committed ) {
228
- _mi_os_commit (_mi_page_map [ 0 ] , submap_size , NULL ); // commit full submap (issue #1087)
243
+ _mi_os_commit (sub0 , submap_size , NULL ); // commit full submap (issue #1087)
229
244
}
230
- if (!mi_page_map_memid .initially_zero ) { // initialize low addresses with NULL
231
- _mi_memzero_aligned (_mi_page_map [ 0 ] , submap_size );
245
+ if (!mi_page_map_memid .initially_zero ) { // initialize low addresses with NULL
246
+ _mi_memzero_aligned (sub0 , submap_size );
232
247
}
248
+ mi_page_map_ensure_committed (0 );
249
+ mi_atomic_store_ptr_release (mi_page_t * , & _mi_page_map [0 ], sub0 );
233
250
234
251
mi_assert_internal (_mi_ptr_page (NULL )== NULL );
235
252
return true;
236
253
}
237
254
255
+
238
256
void _mi_page_map_unsafe_destroy (void ) {
239
257
mi_assert_internal (_mi_page_map != NULL );
240
258
if (_mi_page_map == NULL ) return ;
@@ -258,29 +276,9 @@ void _mi_page_map_unsafe_destroy(void) {
258
276
}
259
277
260
278
261
- #define MI_PAGE_MAP_ENTRIES_PER_CBIT (MI_PAGE_MAP_COUNT / MI_BFIELD_BITS)
262
-
263
- static inline bool mi_page_map_is_committed (size_t idx , size_t * pbit_idx ) {
264
- mi_bfield_t commit = mi_atomic_load_relaxed (& mi_page_map_commit );
265
- const size_t bit_idx = idx /MI_PAGE_MAP_ENTRIES_PER_CBIT ;
266
- mi_assert_internal (bit_idx < MI_BFIELD_BITS );
267
- if (pbit_idx != NULL ) { * pbit_idx = bit_idx ; }
268
- return ((commit & (MI_ZU (1 ) << bit_idx )) != 0 );
269
- }
270
-
271
- static mi_page_t * * mi_page_map_ensure_committed (size_t idx ) {
272
- size_t bit_idx ;
273
- if mi_unlikely (!mi_page_map_is_committed (idx , & bit_idx )) {
274
- uint8_t * start = (uint8_t * )& _mi_page_map [bit_idx * MI_PAGE_MAP_ENTRIES_PER_CBIT ];
275
- _mi_os_commit (start , MI_PAGE_MAP_ENTRIES_PER_CBIT * sizeof (mi_page_t * * ), NULL );
276
- mi_atomic_or_acq_rel (& mi_page_map_commit , MI_ZU (1 ) << bit_idx );
277
- }
278
- return mi_atomic_load_ptr_acquire (mi_page_t * , & _mi_page_map [idx ]); // _mi_page_map_at(idx);
279
- }
280
-
281
- static mi_page_t * * mi_page_map_ensure_at (size_t idx ) {
279
+ static mi_page_t * * mi_page_map_ensure_submap_at (size_t idx ) {
282
280
mi_page_t * * sub = mi_page_map_ensure_committed (idx );
283
- if mi_unlikely (sub == NULL || idx == 0 /* low addresses */ ) {
281
+ if mi_unlikely (sub == NULL ) {
284
282
// sub map not yet allocated, alloc now
285
283
mi_memid_t memid ;
286
284
mi_page_t * * expect = sub ;
@@ -306,7 +304,7 @@ static mi_page_t** mi_page_map_ensure_at(size_t idx) {
306
304
static void mi_page_map_set_range (mi_page_t * page , size_t idx , size_t sub_idx , size_t slice_count ) {
307
305
// is the page map area that contains the page address committed?
308
306
while (slice_count > 0 ) {
309
- mi_page_t * * sub = mi_page_map_ensure_at (idx );
307
+ mi_page_t * * sub = mi_page_map_ensure_submap_at (idx );
310
308
// set the offsets for the page
311
309
while (sub_idx < MI_PAGE_MAP_SUB_COUNT ) {
312
310
sub [sub_idx ] = page ;
0 commit comments