< 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 >