< prev index next >

src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp

Print this page
rev 8155 : 8170409: CMS: Crash in CardTableModRefBSForCTRS::process_chunk_boundaries

@@ -450,13 +450,17 @@
 
   // Do a dirty read here. If we pass the conditional then take the rare
   // event lock and do the read again in case some other thread had already
   // succeeded and done the resize.
   int cur_collection = Universe::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]) {
 
         // Should we delete the old?
         if (_lowest_non_clean[i] != NULL) {

@@ -472,11 +476,12 @@
           _lowest_non_clean_base_chunk_index[i] = addr_to_chunk_index(covered.start());
           for (int j = 0; j < (int)n_chunks; j++)
             _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.
   lowest_non_clean                  = _lowest_non_clean[i];
   lowest_non_clean_base_chunk_index = _lowest_non_clean_base_chunk_index[i];
< prev index next >