Skip to content

[release/7.0] Crash when region survives >2GB #80392

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/coreclr/gc/env/gcenv.base.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x)
#define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT 0x8013200B
#define CLR_E_GC_BAD_HARD_LIMIT 0x8013200D
#define CLR_E_GC_LARGE_PAGE_MISSING_HARD_LIMIT 0x8013200E
#define CLR_E_GC_BAD_REGION_SIZE 0x8013200F

#define NOERROR 0x0
#define ERROR_TIMEOUT 1460
Expand Down
38 changes: 22 additions & 16 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23071,15 +23071,15 @@ void gc_heap::sync_promoted_bytes()
total_old_card_surv += g_heaps[hp_idx]->old_card_survived_per_region[region_index];
}

heap_segment_survived (current_region) = (int)total_surv;
heap_segment_survived (current_region) = total_surv;
heap_segment_old_card_survived (current_region) = (int)total_old_card_surv;
#else
heap_segment_survived (current_region) = (int)(survived_per_region[region_index]);
heap_segment_survived (current_region) = survived_per_region[region_index];
heap_segment_old_card_survived (current_region) =
(int)(old_card_survived_per_region[region_index]);
#endif //MULTIPLE_HEAPS

dprintf (REGIONS_LOG, ("region #%d %Ix surv %Id, old card surv %Id",
dprintf (REGIONS_LOG, ("region #%d %Ix surv %zd, old card surv %Id",
region_index,
heap_segment_mem (current_region),
heap_segment_survived (current_region),
Expand Down Expand Up @@ -23273,8 +23273,8 @@ void gc_heap::equalize_promoted_bytes()
{
break;
}
assert (surv_per_heap[i] >= (size_t)heap_segment_survived (region));
dprintf (REGIONS_LOG, ("heap: %d surv: %Id - %Id = %Id",
assert (surv_per_heap[i] >= heap_segment_survived (region));
dprintf (REGIONS_LOG, ("heap: %d surv: %Id - %zd = %Id",
i,
surv_per_heap[i],
heap_segment_survived (region),
Expand All @@ -23285,7 +23285,7 @@ void gc_heap::equalize_promoted_bytes()
heap_segment_next (region) = surplus_regions;
surplus_regions = region;

max_survived = max (max_survived, (size_t)heap_segment_survived (region));
max_survived = max (max_survived, heap_segment_survived (region));
}
if (surv_per_heap[i] < avg_surv_per_heap)
{
Expand All @@ -23303,7 +23303,7 @@ void gc_heap::equalize_promoted_bytes()
heap_segment* next_region;
for (heap_segment* region = surplus_regions; region != nullptr; region = next_region)
{
int size_class = (int)(heap_segment_survived (region)*survived_scale_factor);
size_t size_class = (size_t)(heap_segment_survived (region)*survived_scale_factor);
assert ((0 <= size_class) && (size_class < NUM_SIZE_CLASSES));
next_region = heap_segment_next (region);
heap_segment_next (region) = surplus_regions_by_size_class[size_class];
Expand Down Expand Up @@ -23365,7 +23365,7 @@ void gc_heap::equalize_promoted_bytes()
g_heaps[heap_num]->thread_rw_region_front (gen_idx, region);

// adjust survival for this heap
dprintf (REGIONS_LOG, ("heap: %d surv: %Id + %Id = %Id",
dprintf (REGIONS_LOG, ("heap: %d surv: %Id + %zd = %Id",
heap_num,
surv_per_heap[heap_num],
heap_segment_survived (region),
Expand Down Expand Up @@ -31340,7 +31340,7 @@ heap_segment* gc_heap::find_first_valid_region (heap_segment* region, bool compa
if (heap_segment_swept_in_plan (current_region))
{
int gen_num = heap_segment_gen_num (current_region);
dprintf (REGIONS_LOG, ("threading SIP region %Ix surv %Id onto gen%d",
dprintf (REGIONS_LOG, ("threading SIP region %Ix surv %zd onto gen%d",
heap_segment_mem (current_region), heap_segment_survived (current_region), gen_num));

generation* gen = generation_of (gen_num);
Expand Down Expand Up @@ -31667,7 +31667,7 @@ bool gc_heap::should_sweep_in_plan (heap_segment* region)
assert (heap_segment_gen_num (region) == heap_segment_plan_gen_num (region));

int surv_ratio = (int)(((double)heap_segment_survived (region) * 100.0) / (double)basic_region_size);
dprintf (2222, ("SSIP: region %Ix surv %Id / %Id = %d%%(%d)",
dprintf (2222, ("SSIP: region %p surv %d / %zd = %d%%(%d)",
heap_segment_mem (region),
heap_segment_survived (region),
basic_region_size,
Expand Down Expand Up @@ -31875,14 +31875,14 @@ void gc_heap::sweep_region_in_plan (heap_segment* region,

#ifdef _DEBUG
size_t region_index = get_basic_region_index_for_address (heap_segment_mem (region));
dprintf (REGIONS_LOG, ("region #%d %Ix survived %Id, %s recorded %Id",
dprintf (REGIONS_LOG, ("region #%d %Ix survived %zd, %s recorded %Id",
region_index, heap_segment_mem (region), survived,
((survived == (size_t)heap_segment_survived (region)) ? "same as" : "diff from"),
((survived == heap_segment_survived (region)) ? "same as" : "diff from"),
heap_segment_survived (region)));
#ifdef MULTIPLE_HEAPS
assert (survived <= (size_t)heap_segment_survived (region));
assert (survived <= heap_segment_survived (region));
#else
assert (survived == (size_t)heap_segment_survived (region));
assert (survived == heap_segment_survived (region));
#endif //MULTIPLE_HEAPS
#endif //_DEBUG

Expand Down Expand Up @@ -45286,8 +45286,14 @@ HRESULT GCHeap::Initialize()
gc_heap::enable_special_regions_p = (bool)GCConfig::GetGCEnableSpecialRegions();
size_t gc_region_size = (size_t)GCConfig::GetGCRegionSize();

// Adjust GCRegionSize based on how large each heap would be, for smaller heaps we would
// like to keep Region sizes small. We choose between 4, 2 and 1mb based on the calculations
// Constraining the size of region size to be < 2 GB.
if (gc_region_size >= MAX_REGION_SIZE)
{
return CLR_E_GC_BAD_REGION_SIZE;
}

// Adjust GCRegionSize based on how large each heap would be, for smaller heaps we would
// like to keep Region sizes small. We choose between 4, 2 and 1mb based on the calculations
// below (unless its configured explictly) such that there are at least 2 regions available
// except for the smallest case. Now the lowest limit possible is 4mb.
if (gc_region_size == 0)
Expand Down
8 changes: 6 additions & 2 deletions src/coreclr/gc/gcpriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ void GCLogConfig (const char *fmt, ... );

#define MAX_NUM_BUCKETS (MAX_INDEX_POWER2 - MIN_INDEX_POWER2 + 1)

#ifdef USE_REGIONS
#define MAX_REGION_SIZE 0x80000000
#endif // USE_REGIONS

#define MAX_NUM_FREE_SPACES 200
#define MIN_NUM_FREE_SPACES 5

Expand Down Expand Up @@ -5734,6 +5738,7 @@ class heap_segment
uint8_t* saved_allocated;
uint8_t* saved_bg_allocated;
#ifdef USE_REGIONS
size_t survived;
// These generation numbers are initialized to -1.
// For plan_gen_num:
// for all regions in condemned generations it needs
Expand All @@ -5748,7 +5753,6 @@ class heap_segment
// swept_in_plan_p can be folded into gen_num.
bool swept_in_plan_p;
int plan_gen_num;
int survived;
int old_card_survived;
int pinned_survived;
// at the end of each GC, we increase each region in the region free list
Expand Down Expand Up @@ -6187,7 +6191,7 @@ int& heap_segment_age_in_free (heap_segment* inst)
return inst->age_in_free;
}
inline
int& heap_segment_survived (heap_segment* inst)
size_t& heap_segment_survived (heap_segment* inst)
{
return inst->survived;
}
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/inc/corerror.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2133,6 +2133,12 @@
<Comment>During a GC initialization, GC large page support requires hard limit settings.</Comment>
</HRESULT>

<HRESULT NumericValue="0x8013200F">
<SymbolicName>CLR_E_GC_BAD_REGION_SIZE</SymbolicName>
<Message>"GC Region Size must be less than 2GB."</Message>
<Comment>During a GC initialization, GC Region Size must be less than 2GB.</Comment>
</HRESULT>

<HRESULT NumericValue="E_ACCESSDENIED">
<SymbolicName>COR_E_UNAUTHORIZEDACCESS</SymbolicName>
<Comment> 0x80070005 // Access is denied.</Comment>
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/pal/prebuilt/corerror/mscorurt.rc
Original file line number Diff line number Diff line change
Expand Up @@ -301,5 +301,6 @@ BEGIN
MSG_FOR_URT_HR(CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT) "GCHeapAffinitizeRanges configuration string has invalid format."
MSG_FOR_URT_HR(CLR_E_GC_BAD_HARD_LIMIT) "GC heap hard limit configuration is invalid."
MSG_FOR_URT_HR(CLR_E_GC_LARGE_PAGE_MISSING_HARD_LIMIT) "GC large page support requires hard limit settings."
MSG_FOR_URT_HR(CLR_E_GC_BAD_REGION_SIZE) "GC Region Size must be less than 2GB."
MSG_FOR_URT_HR(COR_E_BADIMAGEFORMAT) "The format of a DLL or executable being loaded is invalid."
END
1 change: 1 addition & 0 deletions src/coreclr/pal/prebuilt/inc/corerror.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@
#define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT EMAKEHR(0x200b)
#define CLR_E_GC_BAD_HARD_LIMIT EMAKEHR(0x200d)
#define CLR_E_GC_LARGE_PAGE_MISSING_HARD_LIMIT EMAKEHR(0x200e)
#define CLR_E_GC_BAD_REGION_SIZE EMAKEHR(0x200f)
#define COR_E_UNAUTHORIZEDACCESS E_ACCESSDENIED
#define COR_E_ARGUMENT E_INVALIDARG
#define COR_E_INVALIDCAST E_NOINTERFACE
Expand Down