ensure volatile declaration for abandoned_next field

This commit is contained in:
daan 2019-08-23 13:44:43 -07:00
parent a1c5218ff5
commit b511309709
3 changed files with 11 additions and 8 deletions

View File

@ -204,7 +204,7 @@ typedef enum mi_page_kind_e {
typedef struct mi_segment_s { typedef struct mi_segment_s {
struct mi_segment_s* next; struct mi_segment_s* next;
struct mi_segment_s* prev; 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 abandoned; // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`)
size_t used; // count of pages in use (`used <= capacity`) size_t used; // count of pages in use (`used <= capacity`)
size_t capacity; // count of available pages (`#free + used`) size_t capacity; // count of available pages (`#free + used`)

View File

@ -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 // - adjust with 3 because we use do not round the first 8 sizes
// which each get an exact bin // which each get an exact bin
bin = ((b << 2) + (uint8_t)((wsize >> (b - 2)) & 0x03)) - 3; 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); mi_assert_internal(bin > 0 && bin <= MI_BIN_HUGE);
return bin; return bin;

View File

@ -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_segment_remove_from_free_queue(segment,tld);
mi_assert_internal(segment->next == NULL && segment->prev == NULL); mi_assert_internal(segment->next == NULL && segment->prev == NULL);
// all pages in the segment are abandoned; add it to the abandoned list // all pages in the segment are abandoned; add it to the abandoned list
segment->thread_id = 0; _mi_stat_increase(&tld->stats->segments_abandoned, 1);
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_segments_track_size(-((long)segment->segment_size), tld); 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) { 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; mi_segment_t* segment;
do { do {
segment = (mi_segment_t*)abandoned; 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 if (segment==NULL) break; // stop early if no more segments available
// got it. // got it.