Skip to content

Commit

Permalink
8221360: Eliminate Shared_DirtyCardQ_lock
Browse files Browse the repository at this point in the history
Reviewed-by: tschatzl, iwalulya
  • Loading branch information
Kim Barrett committed Aug 24, 2021
1 parent 928b972 commit 0597cde
Show file tree
Hide file tree
Showing 9 changed files with 27 additions and 157 deletions.
3 changes: 1 addition & 2 deletions src/hotspot/share/gc/g1/g1BarrierSet.cpp
Expand Up @@ -58,8 +58,7 @@ G1BarrierSet::G1BarrierSet(G1CardTable* card_table) :
_satb_mark_queue_buffer_allocator("SATB Buffer Allocator", G1SATBBufferSize),
_dirty_card_queue_buffer_allocator("DC Buffer Allocator", G1UpdateBufferSize),
_satb_mark_queue_set(&_satb_mark_queue_buffer_allocator),
_dirty_card_queue_set(&_dirty_card_queue_buffer_allocator),
_shared_dirty_card_queue(&_dirty_card_queue_set)
_dirty_card_queue_set(&_dirty_card_queue_buffer_allocator)
{}

void G1BarrierSet::enqueue(oop pre_val) {
Expand Down
8 changes: 1 addition & 7 deletions src/hotspot/share/gc/g1/g1BarrierSet.hpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -27,7 +27,6 @@

#include "gc/g1/g1DirtyCardQueue.hpp"
#include "gc/g1/g1SATBMarkQueueSet.hpp"
#include "gc/g1/g1SharedDirtyCardQueue.hpp"
#include "gc/shared/cardTable.hpp"
#include "gc/shared/cardTableBarrierSet.hpp"

Expand All @@ -43,7 +42,6 @@ class G1BarrierSet: public CardTableBarrierSet {
BufferNode::Allocator _dirty_card_queue_buffer_allocator;
G1SATBMarkQueueSet _satb_mark_queue_set;
G1DirtyCardQueueSet _dirty_card_queue_set;
G1SharedDirtyCardQueue _shared_dirty_card_queue;

static G1BarrierSet* g1_barrier_set() {
return barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
Expand Down Expand Up @@ -94,10 +92,6 @@ class G1BarrierSet: public CardTableBarrierSet {
return g1_barrier_set()->_dirty_card_queue_set;
}

static G1SharedDirtyCardQueue& shared_dirty_card_queue() {
return g1_barrier_set()->_shared_dirty_card_queue;
}

// Callbacks for runtime accesses.
template <DecoratorSet decorators, typename BarrierSetT = G1BarrierSet>
class AccessBarrier: public ModRefBarrierSet::AccessBarrier<decorators, BarrierSetT> {
Expand Down
3 changes: 0 additions & 3 deletions src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp
Expand Up @@ -546,8 +546,6 @@ void G1DirtyCardQueueSet::abandon_logs() {
}
} closure(*this);
Threads::threads_do(&closure);

G1BarrierSet::shared_dirty_card_queue().reset();
}

void G1DirtyCardQueueSet::concatenate_logs() {
Expand All @@ -571,7 +569,6 @@ void G1DirtyCardQueueSet::concatenate_logs() {
} closure(*this);
Threads::threads_do(&closure);

G1BarrierSet::shared_dirty_card_queue().flush();
enqueue_all_paused_buffers();
verify_num_cards();
set_max_cards(old_limit);
Expand Down
26 changes: 20 additions & 6 deletions src/hotspot/share/gc/g1/g1RemSet.cpp
Expand Up @@ -41,7 +41,6 @@
#include "gc/g1/g1RootClosures.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1ServiceThread.hpp"
#include "gc/g1/g1SharedDirtyCardQueue.hpp"
#include "gc/g1/g1_globals.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionManager.inline.hpp"
Expand Down Expand Up @@ -1688,12 +1687,27 @@ void G1RemSet::refine_card_concurrently(CardValue* const card_ptr,
return;
}

// Re-dirty the card and enqueue in the *shared* queue. Can't use
// the thread-local queue, because that might be the queue that is
// being processed by us; we could be a Java thread conscripted to
// perform refinement on our queue's current buffer.
enqueue_for_reprocessing(card_ptr);
}

// Re-dirty and re-enqueue the card to retry refinement later.
// This is used to deal with a rare race condition in concurrent refinement.
void G1RemSet::enqueue_for_reprocessing(CardValue* card_ptr) {
// We can't use the thread-local queue, because that might be the queue
// that is being processed by us; we could be a Java thread conscripted to
// perform refinement on our queue's current buffer. This situation only
// arises from rare race condition, so it's not worth any significant
// development effort or clever lock-free queue implementation. Instead
// we use brute force, allocating and enqueuing an entire buffer for just
// this card. Since buffers are processed in FIFO order and we try to
// keep some in the queue, it is likely that the racing state will have
// resolved by the time this card comes up for reprocessing.
*card_ptr = G1CardTable::dirty_card_val();
G1BarrierSet::shared_dirty_card_queue().enqueue(card_ptr);
G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
void** buffer = dcqs.allocate_buffer();
size_t index = dcqs.buffer_size() - 1;
buffer[index] = card_ptr;
dcqs.enqueue_completed_buffer(BufferNode::make_node_from_buffer(buffer, index));
}

void G1RemSet::print_periodic_summary_info(const char* header, uint period_count) {
Expand Down
7 changes: 5 additions & 2 deletions src/hotspot/share/gc/g1/g1RemSet.hpp
Expand Up @@ -57,6 +57,9 @@ class HeapRegionClaimer;
// external heap references into it. Uses a mod ref bs to track updates,
// so that they can be used to update the individual region remsets.
class G1RemSet: public CHeapObj<mtGC> {
public:
typedef CardTable::CardValue CardValue;

private:
G1RemSetScanState* _scan_state;

Expand All @@ -72,10 +75,10 @@ class G1RemSet: public CHeapObj<mtGC> {
void print_merge_heap_roots_stats();

void assert_scan_top_is_null(uint hrm_index) NOT_DEBUG_RETURN;
public:

typedef CardTable::CardValue CardValue;
void enqueue_for_reprocessing(CardValue* card_ptr);

public:
// Initialize data that depends on the heap size being known.
void initialize(uint max_reserved_regions);

Expand Down
73 changes: 0 additions & 73 deletions src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.cpp

This file was deleted.

58 changes: 0 additions & 58 deletions src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.hpp

This file was deleted.

3 changes: 0 additions & 3 deletions src/hotspot/share/runtime/mutexLocker.cpp
Expand Up @@ -74,7 +74,6 @@ Mutex* NonJavaThreadsListSync_lock = NULL;
Monitor* CGC_lock = NULL;
Monitor* STS_lock = NULL;
Monitor* G1OldGCCount_lock = NULL;
Mutex* Shared_DirtyCardQ_lock = NULL;
Mutex* G1DetachedRefinementStats_lock = NULL;
Mutex* MarkStackFreeList_lock = NULL;
Mutex* MarkStackChunkList_lock = NULL;
Expand Down Expand Up @@ -217,8 +216,6 @@ void mutex_init() {
if (UseG1GC) {
def(G1OldGCCount_lock , PaddedMonitor, leaf, true, _safepoint_check_always);

def(Shared_DirtyCardQ_lock , PaddedMutex , access + 1, true, _safepoint_check_never);

def(G1DetachedRefinementStats_lock, PaddedMutex, leaf , true, _safepoint_check_never);

def(FreeList_lock , PaddedMutex , leaf , true, _safepoint_check_never);
Expand Down
3 changes: 0 additions & 3 deletions src/hotspot/share/runtime/mutexLocker.hpp
Expand Up @@ -68,9 +68,6 @@ extern Monitor* CGC_lock; // used for coordination betwee
// fore- & background GC threads.
extern Monitor* STS_lock; // used for joining/leaving SuspendibleThreadSet.
extern Monitor* G1OldGCCount_lock; // in support of "concurrent" full gc
extern Mutex* Shared_DirtyCardQ_lock; // Lock protecting dirty card
// queue shared by
// non-Java threads.
extern Mutex* G1DetachedRefinementStats_lock; // Lock protecting detached refinement stats
extern Mutex* MarkStackFreeList_lock; // Protects access to the global mark stack free list.
extern Mutex* MarkStackChunkList_lock; // Protects access to the global mark stack chunk list.
Expand Down

1 comment on commit 0597cde

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.