src/share/vm/memory/metaspace.cpp

Print this page
rev 6878 : 8049599: MetaspaceGC::_capacity_until_GC can overflow

@@ -1413,11 +1413,33 @@
 }
 
 size_t MetaspaceGC::inc_capacity_until_GC(size_t v) {
   assert_is_size_aligned(v, Metaspace::commit_alignment());
 
-  return (size_t)Atomic::add_ptr(v, &_capacity_until_GC);
+  size_t capacity_until_GC = (size_t) _capacity_until_GC;
+  size_t new_value = capacity_until_GC + v;
+
+  if (new_value < capacity_until_GC) {
+    // the addition wrapped around, set new_value to max value
+    new_value = max_uintx;
+  }
+
+  bool cas_succeeded = false;
+  size_t num_retries = 5; // just to limit the number of CAS attempts
+  for (size_t i = 0; i < num_retries; i++) {
+    intptr_t cmp = (intptr_t) capacity_until_GC;
+    intptr_t swap = (intptr_t) new_value;
+    intptr_t prev = Atomic::cmpxchg_ptr(swap, &_capacity_until_GC, cmp);
+
+    if (prev == cmp) {
+      cas_succeeded = true;
+      break;
+    }
+  }
+
+  // if the CAS did not succeed, just return the current value
+  return cas_succeeded ? new_value : _capacity_until_GC;
 }
 
 size_t MetaspaceGC::dec_capacity_until_GC(size_t v) {
   assert_is_size_aligned(v, Metaspace::commit_alignment());