8211718: Supporting multiple concurrent OopStorage iterators
authoreosterlund
Mon, 08 Oct 2018 14:48:12 +0200
changeset 52037 d2a6c3cbc110
parent 52036 5d6d636cefff
child 52038 957de5be48bc
8211718: Supporting multiple concurrent OopStorage iterators Reviewed-by: pliden, kbarrett
src/hotspot/share/gc/shared/oopStorage.cpp
src/hotspot/share/gc/shared/oopStorage.hpp
src/hotspot/share/gc/shared/oopStorageParState.hpp
--- a/src/hotspot/share/gc/shared/oopStorage.cpp	Fri Oct 05 16:47:27 2018 +0200
+++ b/src/hotspot/share/gc/shared/oopStorage.cpp	Mon Oct 08 14:48:12 2018 +0200
@@ -727,7 +727,7 @@
   _allocation_mutex(allocation_mutex),
   _active_mutex(active_mutex),
   _allocation_count(0),
-  _concurrent_iteration_active(false)
+  _concurrent_iteration_count(0)
 {
   _active_array->increment_refcount();
   assert(_active_mutex->rank() < _allocation_mutex->rank(),
@@ -769,7 +769,7 @@
   // blocks available for deletion.
   while (reduce_deferred_updates()) {}
   // Don't interfere with a concurrent iteration.
-  if (_concurrent_iteration_active) return;
+  if (_concurrent_iteration_count > 0) return;
   // Delete empty (and otherwise deletable) blocks from end of _allocation_list.
   for (Block* block = _allocation_list.tail();
        (block != NULL) && block->is_deletable();
@@ -804,7 +804,7 @@
     {
       MutexLockerEx aml(_active_mutex, Mutex::_no_safepoint_check_flag);
       // Don't interfere with a concurrent iteration.
-      if (_concurrent_iteration_active) return;
+      if (_concurrent_iteration_count > 0) return;
       _active_array->remove(block);
     }
     // Remove block from _allocation_list and delete it.
@@ -875,7 +875,7 @@
   _concurrent(concurrent)
 {
   assert(estimated_thread_count > 0, "estimated thread count must be positive");
-  update_iteration_state(true);
+  update_concurrent_iteration_count(1);
   // Get the block count *after* iteration state updated, so concurrent
   // empty block deletion is suppressed and can't reduce the count.  But
   // ensure the count we use was written after the block with that count
@@ -885,14 +885,14 @@
 
 OopStorage::BasicParState::~BasicParState() {
   _storage->relinquish_block_array(_active_array);
-  update_iteration_state(false);
+  update_concurrent_iteration_count(-1);
 }
 
-void OopStorage::BasicParState::update_iteration_state(bool value) {
+void OopStorage::BasicParState::update_concurrent_iteration_count(int value) {
   if (_concurrent) {
     MutexLockerEx ml(_storage->_active_mutex, Mutex::_no_safepoint_check_flag);
-    assert(_storage->_concurrent_iteration_active != value, "precondition");
-    _storage->_concurrent_iteration_active = value;
+    _storage->_concurrent_iteration_count += value;
+    assert(_storage->_concurrent_iteration_count >= 0, "invariant");
   }
 }
 
@@ -954,7 +954,7 @@
 
   st->print("%s: " SIZE_FORMAT " entries in " SIZE_FORMAT " blocks (%.F%%), " SIZE_FORMAT " bytes",
             name(), allocations, blocks, alloc_percentage, total_memory_usage());
-  if (_concurrent_iteration_active) {
+  if (_concurrent_iteration_count > 0) {
     st->print(", concurrent iteration active");
   }
 }
--- a/src/hotspot/share/gc/shared/oopStorage.hpp	Fri Oct 05 16:47:27 2018 +0200
+++ b/src/hotspot/share/gc/shared/oopStorage.hpp	Mon Oct 08 14:48:12 2018 +0200
@@ -220,7 +220,7 @@
   mutable SingleWriterSynchronizer _protect_active;
 
   // mutable because this gets set even for const iteration.
-  mutable bool _concurrent_iteration_active;
+  mutable int _concurrent_iteration_count;
 
   Block* find_block_or_null(const oop* ptr) const;
   void delete_empty_block(const Block& block);
--- a/src/hotspot/share/gc/shared/oopStorageParState.hpp	Fri Oct 05 16:47:27 2018 +0200
+++ b/src/hotspot/share/gc/shared/oopStorageParState.hpp	Mon Oct 08 14:48:12 2018 +0200
@@ -31,22 +31,16 @@
 //////////////////////////////////////////////////////////////////////////////
 // Support for parallel and optionally concurrent state iteration.
 //
-// Parallel iteration is for the exclusive use of the GC.  Other iteration
-// clients must use serial iteration.
-//
 // Concurrent Iteration
 //
 // Iteration involves the _active_array (an ActiveArray), which contains all
 // of the blocks owned by a storage object.
 //
-// At most one concurrent ParState can exist at a time for a given storage
-// object.
-//
-// A concurrent ParState sets the associated storage's
-// _concurrent_iteration_active flag true when the state is constructed, and
-// sets it false when the state is destroyed.  These assignments are made with
+// A concurrent ParState increments the associated storage's
+// _concurrent_iteration_count when the state is constructed, and
+// decrements it when the state is destroyed.  These assignments are made with
 // _active_mutex locked.  Meanwhile, empty block deletion is not done while
-// _concurrent_iteration_active is true.  The flag check and the dependent
+// _concurrent_iteration_count is non-zero.  The counter check and the dependent
 // removal of a block from the _active_array is performed with _active_mutex
 // locked.  This prevents concurrent iteration and empty block deletion from
 // interfering with with each other.
@@ -83,8 +77,8 @@
 // scheduling both operations to run at the same time.
 //
 // ParState<concurrent, is_const>
-//   concurrent must be true if iteration is concurrent with the
-//   mutator, false if iteration is at a safepoint.
+//   concurrent must be true if iteration may be concurrent with the
+//   mutators.
 //
 //   is_const must be true if the iteration is over a constant storage
 //   object, false if the iteration may modify the storage object.
@@ -92,8 +86,7 @@
 // ParState([const] OopStorage* storage)
 //   Construct an object for managing an iteration over storage.  For a
 //   concurrent ParState, empty block deletion for the associated storage
-//   is inhibited for the life of the ParState.  There can be no more
-//   than one live concurrent ParState at a time for a given storage object.
+//   is inhibited for the life of the ParState.
 //
 // template<typename F> void iterate(F f)
 //   Repeatedly claims a block from the associated storage that has
@@ -152,7 +145,7 @@
 
   struct IterationData;
 
-  void update_iteration_state(bool value);
+  void update_concurrent_iteration_count(int value);
   bool claim_next_segment(IterationData* data);
   bool finish_iteration(const IterationData* data) const;