From: Sean Gillespie Date: Thu, 2 Feb 2017 02:32:33 +0000 (-0800) Subject: Fix segment map modification in OOM scenarios (dotnet/coreclr#9241) X-Git-Tag: submit/tizen/20210909.063632~11030^2~8248 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c1740724fff249c6d608fd2fead5300659e62de8;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Fix segment map modification in OOM scenarios (dotnet/coreclr#9241) * Fix an issue where the segment mapping table is not reverted back to its original state when failing to commit the mark array in an OOM scenario. Fixes dotnet/coreclr#9064 * Code review feedback * Update seg_mapping_table before setting g_gc_*_address * Add a barrier between the seg_mapping_table write and updates to g_gc_*_address Commit migrated from https://github.com/dotnet/coreclr/commit/5a7dc18f5985bd28ea798e6a9fc4b8ad5fef09ca --- diff --git a/src/coreclr/src/gc/gc.cpp b/src/coreclr/src/gc/gc.cpp index df77170..66c8b6a 100644 --- a/src/coreclr/src/gc/gc.cpp +++ b/src/coreclr/src/gc/gc.cpp @@ -7042,6 +7042,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, uint8_t* ha = g_gc_highest_address; uint8_t* saved_g_lowest_address = min (start, g_gc_lowest_address); uint8_t* saved_g_highest_address = max (end, g_gc_highest_address); + seg_mapping* new_seg_mapping_table = nullptr; #ifdef BACKGROUND_GC // This value is only for logging purpose - it's not necessarily exactly what we // would commit for mark array but close enough for diagnostics purpose. @@ -7202,14 +7203,18 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, #ifdef GROWABLE_SEG_MAPPING_TABLE { - seg_mapping* new_seg_mapping_table = (seg_mapping*)(mem + st_table_offset_aligned); + new_seg_mapping_table = (seg_mapping*)(mem + st_table_offset_aligned); new_seg_mapping_table = (seg_mapping*)((uint8_t*)new_seg_mapping_table - size_seg_mapping_table_of (0, (align_lower_segment (saved_g_lowest_address)))); memcpy(&new_seg_mapping_table[seg_mapping_word_of(g_gc_lowest_address)], &seg_mapping_table[seg_mapping_word_of(g_gc_lowest_address)], size_seg_mapping_table_of(g_gc_lowest_address, g_gc_highest_address)); - seg_mapping_table = new_seg_mapping_table; + // new_seg_mapping_table gets assigned to seg_mapping_table at the bottom of this function, + // not here. The reason for this is that, if we fail at mark array committing (OOM) and we've + // already switched seg_mapping_table to point to the new mapping table, we'll decommit it and + // run into trouble. By not assigning here, we're making sure that we will not change seg_mapping_table + // if an OOM occurs. } #endif //GROWABLE_SEG_MAPPING_TABLE @@ -7223,7 +7228,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, translated_ct = translate_card_table (ct); dprintf (GC_TABLE_LOG, ("card table: %Ix(translated: %Ix), seg map: %Ix, mark array: %Ix", - (size_t)ct, (size_t)translated_ct, (size_t)seg_mapping_table, (size_t)card_table_mark_array (ct))); + (size_t)ct, (size_t)translated_ct, (size_t)new_seg_mapping_table, (size_t)card_table_mark_array (ct))); #ifdef BACKGROUND_GC if (hp->should_commit_mark_array()) @@ -7301,6 +7306,9 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, g_gc_card_table = translated_ct; } + seg_mapping_table = new_seg_mapping_table; + + GCToOSInterface::FlushProcessWriteBuffers(); g_gc_lowest_address = saved_g_lowest_address; g_gc_highest_address = saved_g_highest_address;