< prev index next >
src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp
Print this page
rev 57716 : [mq]: remove_cbl_mon
*** 1,7 ****
/*
! * Copyright (c) 2001, 2019, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
--- 1,7 ----
/*
! * Copyright (c) 2001, 2020, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*** 27,97 ****
#include "gc/g1/g1ConcurrentRefine.hpp"
#include "gc/g1/g1ConcurrentRefineThread.hpp"
#include "gc/g1/g1DirtyCardQueue.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "logging/log.hpp"
! #include "memory/resourceArea.hpp"
! #include "runtime/handles.inline.hpp"
! #include "runtime/mutexLocker.hpp"
G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, uint worker_id) :
ConcurrentGCThread(),
_vtime_start(0.0),
_vtime_accum(0.0),
_total_refinement_time(),
_total_refined_cards(0),
_worker_id(worker_id),
! _active(false),
! _monitor(NULL),
_cr(cr)
{
- // Each thread has its own monitor. The i-th thread is responsible for signaling
- // to thread i+1 if the number of buffers in the queue exceeds a threshold for this
- // thread. Monitors are also used to wake up the threads during termination.
- // The 0th (primary) worker is notified by mutator threads and has a special monitor.
- if (!is_primary()) {
- _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true,
- Monitor::_safepoint_check_never);
- } else {
- _monitor = DirtyCardQ_CBL_mon;
- }
-
// set name
set_name("G1 Refine#%d", worker_id);
create_and_start();
}
void G1ConcurrentRefineThread::wait_for_completed_buffers() {
! MonitorLocker ml(_monitor, Mutex::_no_safepoint_check_flag);
! while (!should_terminate() && !is_active()) {
! ml.wait();
}
}
- bool G1ConcurrentRefineThread::is_active() {
- G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
- return is_primary() ? dcqs.process_completed_buffers() : _active;
- }
-
void G1ConcurrentRefineThread::activate() {
! MutexLocker x(_monitor, Mutex::_no_safepoint_check_flag);
! if (!is_primary()) {
! set_active(true);
! } else {
! G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
! dcqs.set_process_completed_buffers(true);
}
- _monitor->notify();
}
! void G1ConcurrentRefineThread::deactivate() {
! MutexLocker x(_monitor, Mutex::_no_safepoint_check_flag);
! if (!is_primary()) {
! set_active(false);
} else {
! G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
! dcqs.set_process_completed_buffers(false);
}
}
void G1ConcurrentRefineThread::run_service() {
_vtime_start = os::elapsedVTime();
--- 27,99 ----
#include "gc/g1/g1ConcurrentRefine.hpp"
#include "gc/g1/g1ConcurrentRefineThread.hpp"
#include "gc/g1/g1DirtyCardQueue.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "logging/log.hpp"
! #include "runtime/atomic.hpp"
! #include "runtime/thread.hpp"
G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, uint worker_id) :
ConcurrentGCThread(),
_vtime_start(0.0),
_vtime_accum(0.0),
_total_refinement_time(),
_total_refined_cards(0),
_worker_id(worker_id),
! _notifier(new Semaphore(0)),
! _should_notify(true),
_cr(cr)
{
// set name
set_name("G1 Refine#%d", worker_id);
create_and_start();
}
+ // _notifier and _should_notify form a single-reader / multi-writer
+ // notification mechanism. The thread is the single reader. The writers
+ // are (other) threads that call activate() on the thread.
+
void G1ConcurrentRefineThread::wait_for_completed_buffers() {
! assert(this == Thread::current(), "precondition");
! while (Atomic::load_acquire(&_should_notify)) {
! _notifier->wait();
}
}
void G1ConcurrentRefineThread::activate() {
! assert(this != Thread::current(), "precondition");
! // Notify iff transitioning from needing activation to not. This helps
! // keep the semaphore count bounded and minimizes the work done by
! // activators when the thread is already active.
! if (Atomic::load_acquire(&_should_notify) &&
! Atomic::cmpxchg(&_should_notify, true, false)) {
! _notifier->signal();
}
}
! // Called when no refinement work found for this thread.
! // Returns true if should deactivate.
! bool G1ConcurrentRefineThread::maybe_deactivate(bool more_work) {
! assert(this == Thread::current(), "precondition");
!
! if (more_work) {
! // Suppress unnecessary notifications.
! Atomic::release_store(&_should_notify, false);
! return false;
! } else if (Atomic::load_acquire(&_should_notify)) {
! // Deactivate if no notifications since enabled (see below).
! return true;
} else {
! // Try for more refinement work with notifications enabled, to close
! // race; there could be a plethora of suppressed activation attempts
! // after we found no work but before we enable notifications here
! // (so there could be lots of work for this thread to do), followed
! // by a long time without activation after enabling notifications.
! // But first, clear any pending signals to prevent accumulation.
! while (_notifier->trywait()) {}
! Atomic::release_store(&_should_notify, true);
! return false;
}
}
void G1ConcurrentRefineThread::run_service() {
_vtime_start = os::elapsedVTime();
*** 117,134 ****
sts_join.yield();
continue; // Re-check for termination after yield delay.
}
Ticks start_time = Ticks::now();
! if (!_cr->do_refinement_step(_worker_id, &_total_refined_cards)) {
! break; // No cards to process.
! }
_total_refinement_time += (Ticks::now() - start_time);
}
}
- deactivate();
log_debug(gc, refine)("Deactivated worker %d, off threshold: " SIZE_FORMAT
", current: " SIZE_FORMAT ", refined cards: "
SIZE_FORMAT ", total refined cards: " SIZE_FORMAT,
_worker_id, _cr->deactivation_threshold(_worker_id),
G1BarrierSet::dirty_card_queue_set().num_cards(),
--- 119,135 ----
sts_join.yield();
continue; // Re-check for termination after yield delay.
}
Ticks start_time = Ticks::now();
! bool more_work = _cr->do_refinement_step(_worker_id, &_total_refined_cards);
_total_refinement_time += (Ticks::now() - start_time);
+
+ if (maybe_deactivate(more_work)) break;
}
}
log_debug(gc, refine)("Deactivated worker %d, off threshold: " SIZE_FORMAT
", current: " SIZE_FORMAT ", refined cards: "
SIZE_FORMAT ", total refined cards: " SIZE_FORMAT,
_worker_id, _cr->deactivation_threshold(_worker_id),
G1BarrierSet::dirty_card_queue_set().num_cards(),
*** 144,151 ****
log_debug(gc, refine)("Stopping %d", _worker_id);
}
void G1ConcurrentRefineThread::stop_service() {
! MutexLocker x(_monitor, Mutex::_no_safepoint_check_flag);
! _monitor->notify();
}
--- 145,151 ----
log_debug(gc, refine)("Stopping %d", _worker_id);
}
void G1ConcurrentRefineThread::stop_service() {
! activate();
}
< prev index next >