@@ -24,7 +24,7 @@ terms of the MIT license. A copy of the license can be found in the file
2424typedef bool (heap_page_visitor_fun )(mi_heap_t * heap , mi_page_queue_t * pq , mi_page_t * page , void * arg1 , void * arg2 );
2525
2626// Visit all pages in a heap; returns `false` if break was called.
27- static bool mi_heap_visit_pages (mi_heap_t * heap , heap_page_visitor_fun * fn , void * arg1 , void * arg2 )
27+ static bool mi_heap_visit_pages (mi_heap_t * heap , heap_page_visitor_fun * fn , bool include_full , void * arg1 , void * arg2 )
2828{
2929 if (heap == NULL || heap -> page_count == 0 ) return 0 ;
3030
@@ -34,7 +34,8 @@ static bool mi_heap_visit_pages(mi_heap_t* heap, heap_page_visitor_fun* fn, void
3434 size_t count = 0 ;
3535 #endif
3636
37- for (size_t i = 0 ; i <= MI_BIN_FULL ; i ++ ) {
37+ const size_t max_bin = (include_full ? MI_BIN_FULL : MI_BIN_FULL - 1 );
38+ for (size_t i = 0 ; i <= max_bin ; i ++ ) {
3839 mi_page_queue_t * pq = & heap -> pages [i ];
3940 mi_page_t * page = pq -> first ;
4041 while (page != NULL ) {
@@ -47,7 +48,7 @@ static bool mi_heap_visit_pages(mi_heap_t* heap, heap_page_visitor_fun* fn, void
4748 page = next ; // and continue
4849 }
4950 }
50- mi_assert_internal (count == total );
51+ mi_assert_internal (! include_full || count == total );
5152 return true;
5253}
5354
@@ -67,7 +68,7 @@ static bool mi_heap_page_is_valid(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_
6768#if MI_DEBUG >=3
6869static bool mi_heap_is_valid (mi_heap_t * heap ) {
6970 mi_assert_internal (heap != NULL );
70- mi_heap_visit_pages (heap , & mi_heap_page_is_valid , NULL , NULL );
71+ mi_heap_visit_pages (heap , & mi_heap_page_is_valid , true, NULL , NULL );
7172 return true;
7273}
7374#endif
@@ -143,7 +144,7 @@ static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect)
143144
144145 // if abandoning, mark all pages to no longer add to delayed_free
145146 if (collect == MI_ABANDON ) {
146- mi_heap_visit_pages (heap , & mi_heap_page_never_delayed_free , NULL , NULL );
147+ mi_heap_visit_pages (heap , & mi_heap_page_never_delayed_free , true, NULL , NULL );
147148 }
148149
149150 // free all current thread delayed blocks.
@@ -154,7 +155,7 @@ static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect)
154155 _mi_heap_collect_retired (heap , force );
155156
156157 // collect all pages owned by this thread
157- mi_heap_visit_pages (heap , & mi_heap_page_collect , & collect , NULL );
158+ mi_heap_visit_pages (heap , & mi_heap_page_collect , ( collect != MI_NORMAL ), & collect , NULL ); // normally don't visit full pages, issue #1220
158159 mi_assert_internal ( collect != MI_ABANDON || mi_atomic_load_ptr_acquire (mi_block_t ,& heap -> thread_delayed_free ) == NULL );
159160
160161 // collect segments (purge pages, this can be expensive so don't force on abandonment)
@@ -359,7 +360,7 @@ static bool _mi_heap_page_destroy(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_
359360}
360361
361362void _mi_heap_destroy_pages (mi_heap_t * heap ) {
362- mi_heap_visit_pages (heap , & _mi_heap_page_destroy , NULL , NULL );
363+ mi_heap_visit_pages (heap , & _mi_heap_page_destroy , true, NULL , NULL );
363364 mi_heap_reset_pages (heap );
364365}
365366
@@ -530,7 +531,7 @@ bool mi_heap_check_owned(mi_heap_t* heap, const void* p) {
530531 if (heap == NULL || !mi_heap_is_initialized (heap )) return false;
531532 if (((uintptr_t )p & (MI_INTPTR_SIZE - 1 )) != 0 ) return false; // only aligned pointers
532533 bool found = false;
533- mi_heap_visit_pages (heap , & mi_heap_page_check_owned , (void * )p , & found );
534+ mi_heap_visit_pages (heap , & mi_heap_page_check_owned , true, (void * )p , & found );
534535 return found ;
535536}
536537
@@ -696,7 +697,7 @@ static bool mi_heap_visit_areas_page(mi_heap_t* heap, mi_page_queue_t* pq, mi_pa
696697// Visit all heap pages as areas
697698static bool mi_heap_visit_areas (const mi_heap_t * heap , mi_heap_area_visit_fun * visitor , void * arg ) {
698699 if (visitor == NULL ) return false;
699- return mi_heap_visit_pages ((mi_heap_t * )heap , & mi_heap_visit_areas_page , (void * )(visitor ), arg ); // note: function pointer to void* :-{
700+ return mi_heap_visit_pages ((mi_heap_t * )heap , & mi_heap_visit_areas_page , true, (void * )(visitor ), arg ); // note: function pointer to void* :-{
700701}
701702
702703// Just to pass arguments
0 commit comments