diff --git a/include/mimalloc-types.h b/include/mimalloc-types.h index c0778f8..dd1f05e 100644 --- a/include/mimalloc-types.h +++ b/include/mimalloc-types.h @@ -204,7 +204,7 @@ typedef enum mi_page_kind_e { typedef struct mi_segment_s { struct mi_segment_s* next; struct mi_segment_s* prev; - struct mi_segment_s* abandoned_next; + volatile struct mi_segment_s* abandoned_next; size_t abandoned; // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`) size_t used; // count of pages in use (`used <= capacity`) size_t capacity; // count of available pages (`#free + used`) diff --git a/src/page-queue.c b/src/page-queue.c index e476403..859b1d5 100644 --- a/src/page-queue.c +++ b/src/page-queue.c @@ -130,6 +130,7 @@ extern inline uint8_t _mi_bin(size_t size) { // - adjust with 3 because we use do not round the first 8 sizes // which each get an exact bin bin = ((b << 2) + (uint8_t)((wsize >> (b - 2)) & 0x03)) - 3; + mi_assert_internal(bin < MI_BIN_HUGE); } mi_assert_internal(bin > 0 && bin <= MI_BIN_HUGE); return bin; diff --git a/src/segment.c b/src/segment.c index d5a2288..6379b24 100644 --- a/src/segment.c +++ b/src/segment.c @@ -558,13 +558,15 @@ static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld) { mi_segment_remove_from_free_queue(segment,tld); mi_assert_internal(segment->next == NULL && segment->prev == NULL); // all pages in the segment are abandoned; add it to the abandoned list - segment->thread_id = 0; - do { - segment->abandoned_next = (mi_segment_t*)abandoned; - } while (!mi_atomic_compare_exchange_ptr((volatile void**)&abandoned, segment, segment->abandoned_next)); - mi_atomic_increment(&abandoned_count); - _mi_stat_increase(&tld->stats->segments_abandoned,1); + _mi_stat_increase(&tld->stats->segments_abandoned, 1); mi_segments_track_size(-((long)segment->segment_size), tld); + segment->thread_id = 0; + mi_segment_t* next; + do { + next = (mi_segment_t*)abandoned; + mi_atomic_write_ptr((volatile void**)&segment->abandoned_next, next); + } while (!mi_atomic_compare_exchange_ptr((volatile void**)&abandoned, segment, next)); + mi_atomic_increment(&abandoned_count); } void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld) { @@ -598,7 +600,7 @@ bool _mi_segment_try_reclaim_abandoned( mi_heap_t* heap, bool try_all, mi_segmen mi_segment_t* segment; do { segment = (mi_segment_t*)abandoned; - } while(segment != NULL && !mi_atomic_compare_exchange_ptr((volatile void**)&abandoned, segment->abandoned_next, segment)); + } while(segment != NULL && !mi_atomic_compare_exchange_ptr((volatile void**)&abandoned, (mi_segment_t*)segment->abandoned_next, segment)); if (segment==NULL) break; // stop early if no more segments available // got it.