/* * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Google 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. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef SHARE_GC_G1_G1EPOCHSYNCHRONIZER_HPP #define SHARE_GC_G1_G1EPOCHSYNCHRONIZER_HPP #include "memory/allocation.hpp" class JavaThread; // G1EpochSynchronizer implements an epoch synchronization protocol in order to // support asymmetric Dekker-style synchronization between all mutator threads // and the thread doing concurrent refinement work. The epoch synchronization // protocol guarantees that all mutator stores to Java heap prior to the // initiation of the protocol are visible to the thread that initiates the // protocol when the protocol finishes. // // TODO: Finish the description. // An example of the protocol is below. // // A mutator thread updates its local epoch to the global epoch at code locations // that imply a store-load fence, such as safe point that are taken, handshake // with VM, and slow path for lock acquisition. class G1EpochSynchronizer : public CHeapObj { enum UrgencyLevel { // Only reads epoch of mutator threads, do not initiate handshake UrgencyLevel1, // Possibly initiate a handshake with mutator threads UrgencyLevel2, UrgencyLevelMax = UrgencyLevel2 }; static const uintx _EPOCH_RESET_THRESHOLD = DEBUG_ONLY(512) NOT_DEBUG(max_uintx / 4 * 3); // The global epoch that each Java thread will copy to its local epoch. static volatile uintx _global_epoch; static volatile bool _reset_all_epoch_scheduled; // The largest global epoch that we know all Java threads has copied. // _global_epoch >= _global_frontier should always be true. static volatile uintx _global_frontier; uintx _required_frontier; UrgencyLevel _current_urgency; // Updates _global_frontier to MAX(_global_frontier, latest_frontier) static void update_global_frontier(uintx latest_frontier); // Returns true iff latest frontier >= required_frontier, and in that case // calls update_global_frontier(). static bool check_and_update_frontier(uintx required_frontier); // Returns true iff all epoch/frontier counters have been reset. static bool check_and_handle_overflow(uintx global_epoch); public: static uintx global_epoch(); static void reset_all_epoch(); G1EpochSynchronizer(UrgencyLevel start_urgency = UrgencyLevel1); void increase_urgency(); void start_synchronizing(); bool try_synchronize(); }; // Statistic counters for all instances of G1EpochSynchronizer. class G1EpochSynchronizerCounters : public CHeapObj { volatile size_t _num_fast_sync; volatile size_t _num_no_handshake_sync; volatile size_t _num_handshake_sync; volatile size_t _num_reset_global_epoch; volatile size_t _no_handshake_accum_time_counter; volatile size_t _handshake_accum_time_counter; volatile size_t _num_handshake_no_safepoint; volatile size_t _num_handshake_safepoint; public: G1EpochSynchronizerCounters(); volatile size_t& num_fast_sync() { return _num_fast_sync; } volatile size_t& num_no_handshake_sync() { return _num_no_handshake_sync; } volatile size_t& num_handshake_sync() { return _num_handshake_sync; } volatile size_t& num_reset_global_epoch() { return _num_reset_global_epoch; } volatile size_t& no_handshake_accum_time_counter() { return _no_handshake_accum_time_counter; } volatile size_t& handshake_accum_time_counter() { return _handshake_accum_time_counter; } volatile size_t& num_handshake_no_safepoint() { return _num_handshake_no_safepoint; } volatile size_t& num_handshake_safepoint() { return _num_handshake_safepoint; } }; #endif // SHARE_GC_G1_G1EPOCHSYNCHRONIZER_HPP