8211718: Supporting multiple concurrent OopStorage iterators
Reviewed-by: pliden, kbarrett
This commit is contained in:
parent
90d6bbd01a
commit
b658954d7e
@ -727,7 +727,7 @@ OopStorage::OopStorage(const char* name,
|
||||
_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 @@ void OopStorage::delete_empty_blocks_safepoint() {
|
||||
// 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 @@ void OopStorage::delete_empty_blocks_concurrent() {
|
||||
{
|
||||
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 @@ OopStorage::BasicParState::BasicParState(const OopStorage* storage,
|
||||
_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(const OopStorage* storage,
|
||||
|
||||
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 @@ void OopStorage::print_on(outputStream* st) const {
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ private:
|
||||
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);
|
||||
|
@ -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 @@ class OopStorage::BasicParState {
|
||||
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user