@@ -30,14 +30,17 @@ terms of the MIT license. A copy of the license can be found in the file
30
30
#define mi_decl_noinline __declspec (noinline)
31
31
#define mi_decl_thread __declspec (thread)
32
32
#define mi_decl_cache_align __declspec (align(MI_CACHE_LINE))
33
+ #define mi_decl_weak
33
34
#elif (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) // includes clang and icc
34
35
#define mi_decl_noinline __attribute__ ((noinline))
35
36
#define mi_decl_thread __thread
36
37
#define mi_decl_cache_align __attribute__ ((aligned(MI_CACHE_LINE)))
38
+ #define mi_decl_weak __attribute__ ((weak))
37
39
#else
38
40
#define mi_decl_noinline
39
41
#define mi_decl_thread __thread // hope for the best :-)
40
42
#define mi_decl_cache_align
43
+ #define mi_decl_weak
41
44
#endif
42
45
43
46
#if defined(__EMSCRIPTEN__) && !defined(__wasi__)
@@ -88,7 +91,7 @@ void _mi_thread_data_collect(void);
88
91
89
92
// os.c
90
93
void _mi_os_init (void ); // called from process init
91
- void * _mi_os_alloc (size_t size, mi_memid_t * memid, mi_stats_t * stats);
94
+ void * _mi_os_alloc (size_t size, mi_memid_t * memid, mi_stats_t * stats);
92
95
void _mi_os_free (void * p, size_t size, mi_memid_t memid, mi_stats_t * stats);
93
96
void _mi_os_free_ex (void * p, size_t size, bool still_committed, mi_memid_t memid, mi_stats_t * stats);
94
97
@@ -121,9 +124,21 @@ void* _mi_arena_alloc(size_t size, bool commit, bool allow_large, mi_arena_
121
124
void * _mi_arena_alloc_aligned (size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t * memid, mi_os_tld_t * tld);
122
125
bool _mi_arena_memid_is_suitable (mi_memid_t memid, mi_arena_id_t request_arena_id);
123
126
bool _mi_arena_contains (const void * p);
124
- void _mi_arena_collect (bool force_purge, mi_stats_t * stats);
127
+ void _mi_arenas_collect (bool force_purge, mi_stats_t * stats);
125
128
void _mi_arena_unsafe_destroy_all (mi_stats_t * stats);
126
129
130
+ bool _mi_arena_segment_clear_abandoned (mi_segment_t * segment);
131
+ void _mi_arena_segment_mark_abandoned (mi_segment_t * segment);
132
+ size_t _mi_arena_segment_abandoned_count (void );
133
+
134
+ typedef struct mi_arena_field_cursor_s { // abstract
135
+ mi_arena_id_t start;
136
+ int count;
137
+ size_t bitmap_idx;
138
+ } mi_arena_field_cursor_t ;
139
+ void _mi_arena_field_cursor_init (mi_heap_t * heap, mi_arena_field_cursor_t * current);
140
+ mi_segment_t * _mi_arena_segment_clear_abandoned_next (mi_arena_field_cursor_t * previous);
141
+
127
142
// "segment-map.c"
128
143
void _mi_segment_map_allocated_at (const mi_segment_t * segment);
129
144
void _mi_segment_map_freed_at (const mi_segment_t * segment);
@@ -132,17 +147,18 @@ void _mi_segment_map_freed_at(const mi_segment_t* segment);
132
147
mi_page_t * _mi_segment_page_alloc (mi_heap_t * heap, size_t block_size, size_t page_alignment, mi_segments_tld_t * tld, mi_os_tld_t * os_tld);
133
148
void _mi_segment_page_free (mi_page_t * page, bool force, mi_segments_tld_t * tld);
134
149
void _mi_segment_page_abandon (mi_page_t * page, mi_segments_tld_t * tld);
135
- uint8_t * _mi_segment_page_start (const mi_segment_t * segment, const mi_page_t * page, size_t block_size, size_t * page_size, size_t * pre_size); // page start for any page
150
+ uint8_t * _mi_segment_page_start (const mi_segment_t * segment, const mi_page_t * page, size_t * page_size);
136
151
137
152
#if MI_HUGE_PAGE_ABANDON
138
153
void _mi_segment_huge_page_free (mi_segment_t * segment, mi_page_t * page, mi_block_t * block);
139
154
#else
140
155
void _mi_segment_huge_page_reset (mi_segment_t * segment, mi_page_t * page, mi_block_t * block);
141
156
#endif
142
157
143
- void _mi_segment_thread_collect ( mi_segments_tld_t * tld);
158
+ void _mi_segments_collect ( bool force, mi_segments_tld_t * tld);
144
159
void _mi_abandoned_reclaim_all (mi_heap_t * heap, mi_segments_tld_t * tld);
145
160
void _mi_abandoned_await_readers (void );
161
+ bool _mi_segment_attempt_reclaim (mi_heap_t * heap, mi_segment_t * segment);
146
162
147
163
// "page.c"
148
164
void * _mi_malloc_generic (mi_heap_t * heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept mi_attr_malloc;
@@ -180,23 +196,28 @@ mi_msecs_t _mi_clock_end(mi_msecs_t start);
180
196
mi_msecs_t _mi_clock_start (void );
181
197
182
198
// "alloc.c"
183
- void * _mi_page_malloc (mi_heap_t * heap, mi_page_t * page, size_t size, bool zero) mi_attr_noexcept; // called from `_mi_malloc_generic`
199
+ void * _mi_page_malloc_zero (mi_heap_t * heap, mi_page_t * page, size_t size, bool zero) mi_attr_noexcept; // called from `_mi_malloc_generic`
200
+ void * _mi_page_malloc (mi_heap_t * heap, mi_page_t * page, size_t size) mi_attr_noexcept; // called from `_mi_heap_malloc_aligned`
201
+ void * _mi_page_malloc_zeroed (mi_heap_t * heap, mi_page_t * page, size_t size) mi_attr_noexcept; // called from `_mi_heap_malloc_aligned`
184
202
void * _mi_heap_malloc_zero (mi_heap_t * heap, size_t size, bool zero) mi_attr_noexcept;
185
203
void * _mi_heap_malloc_zero_ex (mi_heap_t * heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept; // called from `_mi_heap_malloc_aligned`
186
204
void * _mi_heap_realloc_zero (mi_heap_t * heap, void * p, size_t newsize, bool zero) mi_attr_noexcept;
187
- mi_block_t * _mi_page_ptr_unalign (const mi_segment_t * segment, const mi_page_t * page, const void * p);
205
+ mi_block_t * _mi_page_ptr_unalign (const mi_page_t * page, const void * p);
188
206
bool _mi_free_delayed_block (mi_block_t * block);
189
- void _mi_free_generic (const mi_segment_t * segment, mi_page_t * page, bool is_local, void * p) mi_attr_noexcept; // for runtime integration
207
+ void _mi_free_generic (mi_segment_t * segment, mi_page_t * page, bool is_local, void * p) mi_attr_noexcept; // for runtime integration
190
208
void _mi_padding_shrink (const mi_page_t * page, const mi_block_t * block, const size_t min_size);
191
209
192
- // option.c, c primitives
210
+ // "libc.c"
211
+ #include < stdarg.h>
212
+ void _mi_vsnprintf (char * buf, size_t bufsize, const char * fmt, va_list args);
213
+ void _mi_snprintf (char * buf, size_t buflen, const char * fmt, ...);
193
214
char _mi_toupper (char c);
194
215
int _mi_strnicmp (const char * s, const char * t, size_t n);
195
216
void _mi_strlcpy (char * dest, const char * src, size_t dest_size);
196
217
void _mi_strlcat (char * dest, const char * src, size_t dest_size);
197
218
size_t _mi_strlen (const char * s);
198
219
size_t _mi_strnlen (const char * s, size_t max_len);
199
-
220
+ bool _mi_getenv ( const char * name, char * result, size_t result_size);
200
221
201
222
#if MI_DEBUG>1
202
223
bool _mi_page_is_valid (mi_page_t * page);
@@ -293,6 +314,12 @@ static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) {
293
314
}
294
315
}
295
316
317
+ // Align a pointer upwards
318
+ static inline void * mi_align_up_ptr (void * p, size_t alignment) {
319
+ return (void *)_mi_align_up ((uintptr_t )p, alignment);
320
+ }
321
+
322
+
296
323
// Divide upwards: `s <= _mi_divide_up(s,d)*d < s+d`.
297
324
static inline uintptr_t _mi_divide_up (uintptr_t size, size_t divider) {
298
325
mi_assert_internal (divider != 0 );
@@ -391,13 +418,19 @@ static inline mi_page_t* _mi_heap_get_free_small_page(mi_heap_t* heap, size_t si
391
418
// Large aligned blocks may be aligned at N*MI_SEGMENT_SIZE (inside a huge segment > MI_SEGMENT_SIZE),
392
419
// and we need align "down" to the segment info which is `MI_SEGMENT_SIZE` bytes before it;
393
420
// therefore we align one byte before `p`.
421
+ // We check for NULL afterwards on 64-bit systems to improve codegen for `mi_free`.
394
422
static inline mi_segment_t * _mi_ptr_segment (const void * p) {
395
- mi_assert_internal (p != NULL );
396
- return (mi_segment_t *)(((uintptr_t )p - 1 ) & ~MI_SEGMENT_MASK);
423
+ mi_segment_t * const segment = (mi_segment_t *)(((uintptr_t )p - 1 ) & ~MI_SEGMENT_MASK);
424
+ #if MI_INTPTR_SIZE <= 4
425
+ return (p==NULL ? NULL : segment);
426
+ #else
427
+ return ((intptr_t )segment <= 0 ? NULL : segment);
428
+ #endif
397
429
}
398
430
399
431
// Segment belonging to a page
400
432
static inline mi_segment_t * _mi_page_segment (const mi_page_t * page) {
433
+ mi_assert_internal (page!=NULL );
401
434
mi_segment_t * segment = _mi_ptr_segment (page);
402
435
mi_assert_internal (segment == NULL || page == &segment->pages [page->segment_idx ]);
403
436
return segment;
@@ -421,33 +454,28 @@ static inline mi_page_t* _mi_segment_page_of(const mi_segment_t* segment, const
421
454
}
422
455
423
456
// Quick page start for initialized pages
424
- static inline uint8_t * _mi_page_start (const mi_segment_t * segment, const mi_page_t * page, size_t * page_size ) {
425
- const size_t bsize = page->xblock_size ;
426
- mi_assert_internal (bsize > 0 && (bsize% sizeof ( void *) ) == 0 );
427
- return _mi_segment_page_start (segment, page, bsize, page_size, NULL ) ;
457
+ static inline uint8_t * mi_page_start (const mi_page_t * page) {
458
+ mi_assert_internal ( page->page_start != NULL ) ;
459
+ mi_assert_expensive ( _mi_segment_page_start ( _mi_page_segment (page),page, NULL ) == page-> page_start );
460
+ return page-> page_start ;
428
461
}
429
462
430
463
// Get the page containing the pointer
431
464
static inline mi_page_t * _mi_ptr_page (void * p) {
465
+ mi_assert_internal (p!=NULL );
432
466
return _mi_segment_page_of (_mi_ptr_segment (p), p);
433
467
}
434
468
435
469
// Get the block size of a page (special case for huge objects)
436
470
static inline size_t mi_page_block_size (const mi_page_t * page) {
437
- const size_t bsize = page->xblock_size ;
438
- mi_assert_internal (bsize > 0 );
439
- if mi_likely (bsize < MI_HUGE_BLOCK_SIZE) {
440
- return bsize;
441
- }
442
- else {
443
- size_t psize;
444
- _mi_segment_page_start (_mi_page_segment (page), page, bsize, &psize, NULL );
445
- return psize;
446
- }
471
+ mi_assert_internal (page->block_size > 0 );
472
+ return page->block_size ;
447
473
}
448
474
449
475
static inline bool mi_page_is_huge (const mi_page_t * page) {
450
- return (_mi_page_segment (page)->page_kind == MI_PAGE_HUGE);
476
+ mi_assert_internal ((page->is_huge && _mi_page_segment (page)->page_kind == MI_PAGE_HUGE) ||
477
+ (!page->is_huge && _mi_page_segment (page)->page_kind != MI_PAGE_HUGE));
478
+ return page->is_huge ;
451
479
}
452
480
453
481
// Get the usable block size of a page without fixed padding.
0 commit comments