8170409: CMS: Crash in CardTableModRefBSForCTRS::process_chunk_boundaries
Reviewed-by: simonis, tschatzl, mgerdin, dlong
Contributed-by: gunter.haug@sap.com
--- a/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp Wed Nov 30 22:44:51 2016 +0100
+++ b/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp Fri Dec 02 11:07:27 2016 +0100
@@ -395,9 +395,13 @@
// event lock and do the read again in case some other thread had already
// succeeded and done the resize.
int cur_collection = GenCollectedHeap::heap()->total_collections();
- if (_last_LNC_resizing_collection[i] != cur_collection) {
+ // Updated _last_LNC_resizing_collection[i] must not be visible before
+ // _lowest_non_clean and friends are visible. Therefore use acquire/release
+ // to guarantee this on non TSO architecures.
+ if (OrderAccess::load_acquire(&_last_LNC_resizing_collection[i]) != cur_collection) {
MutexLocker x(ParGCRareEvent_lock);
- if (_last_LNC_resizing_collection[i] != cur_collection) {
+ // This load_acquire is here for clarity only. The MutexLocker already fences.
+ if (OrderAccess::load_acquire(&_last_LNC_resizing_collection[i]) != cur_collection) {
if (_lowest_non_clean[i] == NULL ||
n_chunks != _lowest_non_clean_chunk_size[i]) {
@@ -417,7 +421,8 @@
_lowest_non_clean[i][j] = NULL;
}
}
- _last_LNC_resizing_collection[i] = cur_collection;
+ // Make sure this gets visible only after _lowest_non_clean* was initialized
+ OrderAccess::release_store(&_last_LNC_resizing_collection[i], cur_collection);
}
}
// In any case, now do the initialization.
--- a/hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.hpp Wed Nov 30 22:44:51 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.hpp Fri Dec 02 11:07:27 2016 +0100
@@ -85,7 +85,7 @@
CardArr* _lowest_non_clean;
size_t* _lowest_non_clean_chunk_size;
uintptr_t* _lowest_non_clean_base_chunk_index;
- int* _last_LNC_resizing_collection;
+ volatile int* _last_LNC_resizing_collection;
// Initializes "lowest_non_clean" to point to the array for the region
// covering "sp", and "lowest_non_clean_base_chunk_index" to the chunk