Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp
38920 views
/*1* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPTHREAD_HPP25#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPTHREAD_HPP2627#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"28#include "gc_implementation/shared/concurrentGCThread.hpp"29#include "runtime/thread.inline.hpp"3031class ConcurrentMarkSweepGeneration;32class CMSCollector;3334// The Concurrent Mark Sweep GC Thread35class ConcurrentMarkSweepThread: public ConcurrentGCThread {36friend class VMStructs;37friend class ConcurrentMarkSweepGeneration; // XXX should remove friendship38friend class CMSCollector;39public:40virtual void run();4142private:43static ConcurrentMarkSweepThread* _cmst;44static CMSCollector* _collector;45static SurrogateLockerThread* _slt;46static SurrogateLockerThread::SLT_msg_type _sltBuffer;47static Monitor* _sltMonitor;4849static bool _should_terminate;5051enum CMS_flag_type {52CMS_nil = NoBits,53CMS_cms_wants_token = nth_bit(0),54CMS_cms_has_token = nth_bit(1),55CMS_vm_wants_token = nth_bit(2),56CMS_vm_has_token = nth_bit(3)57};5859static int _CMS_flag;6061static bool CMS_flag_is_set(int b) { return (_CMS_flag & b) != 0; }62static bool set_CMS_flag(int b) { return (_CMS_flag |= b) != 0; }63static bool clear_CMS_flag(int b) { return (_CMS_flag &= ~b) != 0; }64void sleepBeforeNextCycle();6566// CMS thread should yield for a young gen collection, direct allocation,67// and iCMS activity.68static char _pad_1[64 - sizeof(jint)]; // prevent cache-line sharing69static volatile jint _pending_yields;70static volatile jint _pending_decrements; // decrements to _pending_yields71static char _pad_2[64 - sizeof(jint)]; // prevent cache-line sharing7273// Tracing messages, enabled by CMSTraceThreadState.74static inline void trace_state(const char* desc);7576static volatile int _icms_disabled; // a counter to track #iCMS disable & enable77static volatile bool _should_run; // iCMS may run78static volatile bool _should_stop; // iCMS should stop7980// debugging81void verify_ok_to_terminate() const PRODUCT_RETURN;8283public:84// Constructor85ConcurrentMarkSweepThread(CMSCollector* collector);8687static void makeSurrogateLockerThread(TRAPS);88static SurrogateLockerThread* slt() { return _slt; }8990// Tester91bool is_ConcurrentGC_thread() const { return true; }9293static void threads_do(ThreadClosure* tc);9495// Printing96void print_on(outputStream* st) const;97void print() const { print_on(tty); }98static void print_all_on(outputStream* st);99static void print_all() { print_all_on(tty); }100101// Returns the CMS Thread102static ConcurrentMarkSweepThread* cmst() { return _cmst; }103static CMSCollector* collector() { return _collector; }104105// Create and start the CMS Thread, or stop it on shutdown106static ConcurrentMarkSweepThread* start(CMSCollector* collector);107static void stop();108static bool should_terminate() { return _should_terminate; }109110// Synchronization using CMS token111static void synchronize(bool is_cms_thread);112static void desynchronize(bool is_cms_thread);113static bool vm_thread_has_cms_token() {114return CMS_flag_is_set(CMS_vm_has_token);115}116static bool cms_thread_has_cms_token() {117return CMS_flag_is_set(CMS_cms_has_token);118}119static bool vm_thread_wants_cms_token() {120return CMS_flag_is_set(CMS_vm_wants_token);121}122static bool cms_thread_wants_cms_token() {123return CMS_flag_is_set(CMS_cms_wants_token);124}125126// Wait on CMS lock until the next synchronous GC127// or given timeout, whichever is earlier. A timeout value128// of 0 indicates that there is no upper bound on the wait time.129// A concurrent full gc request terminates the wait.130void wait_on_cms_lock(long t_millis);131132// Wait on CMS lock until the next synchronous GC133// or given timeout, whichever is earlier. A timeout value134// of 0 indicates that there is no upper bound on the wait time.135// A concurrent full gc request terminates the wait.136void wait_on_cms_lock_for_scavenge(long t_millis);137138// The CMS thread will yield during the work portion of its cycle139// only when requested to. Both synchronous and asychronous requests140// are provided:141// (1) A synchronous request is used for young gen collections and142// for direct allocations. The requesting thread increments143// _pending_yields at the beginning of an operation, and decrements144// _pending_yields when that operation is completed.145// In turn, the CMS thread yields when _pending_yields is positive,146// and continues to yield until the value reverts to 0.147// (2) An asynchronous request, on the other hand, is used by iCMS148// for the stop_icms() operation. A single yield satisfies all of149// the outstanding asynch yield requests, of which there may150// occasionally be several in close succession. To accomplish151// this, an asynch-requesting thread atomically increments both152// _pending_yields and _pending_decrements. An asynchr requesting153// thread does not wait and "acknowledge" completion of an operation154// and deregister the request, like the synchronous version described155// above does. In turn, after yielding, the CMS thread decrements both156// _pending_yields and _pending_decrements by the value seen in157// _pending_decrements before the decrement.158// NOTE: The above scheme is isomorphic to having two request counters,159// one for async requests and one for sync requests, and for the CMS thread160// to check the sum of the two counters to decide whether it should yield161// and to clear only the async counter when it yields. However, it turns out162// to be more efficient for CMS code to just check a single counter163// _pending_yields that holds the sum (of both sync and async requests), and164// a second counter _pending_decrements that only holds the async requests,165// for greater efficiency, since in a typical CMS run, there are many more166// pontential (i.e. static) yield points than there are actual167// (i.e. dynamic) yields because of requests, which are few and far between.168//169// Note that, while "_pending_yields >= _pending_decrements" is an invariant,170// we cannot easily test that invariant, since the counters are manipulated via171// atomic instructions without explicit locking and we cannot read172// the two counters atomically together: one suggestion is to173// use (for example) 16-bit counters so as to be able to read the174// two counters atomically even on 32-bit platforms. Notice that175// the second assert in acknowledge_yield_request() below does indeed176// check a form of the above invariant, albeit indirectly.177178static void increment_pending_yields() {179Atomic::inc(&_pending_yields);180assert(_pending_yields >= 0, "can't be negative");181}182static void decrement_pending_yields() {183Atomic::dec(&_pending_yields);184assert(_pending_yields >= 0, "can't be negative");185}186static void asynchronous_yield_request() {187assert(CMSIncrementalMode, "Currently only used w/iCMS");188increment_pending_yields();189Atomic::inc(&_pending_decrements);190assert(_pending_decrements >= 0, "can't be negative");191}192static void acknowledge_yield_request() {193jint decrement = _pending_decrements;194if (decrement > 0) {195assert(CMSIncrementalMode, "Currently only used w/iCMS");196// Order important to preserve: _pending_yields >= _pending_decrements197Atomic::add(-decrement, &_pending_decrements);198Atomic::add(-decrement, &_pending_yields);199assert(_pending_decrements >= 0, "can't be negative");200assert(_pending_yields >= 0, "can't be negative");201}202}203static bool should_yield() { return _pending_yields > 0; }204205// CMS incremental mode.206static void start_icms(); // notify thread to start a quantum of work207static void stop_icms(); // request thread to stop working208void icms_wait(); // if asked to stop, wait until notified to start209210// Incremental mode is enabled globally by the flag CMSIncrementalMode. It211// must also be enabled/disabled dynamically to allow foreground collections.212#define ICMS_ENABLING_ASSERT \213assert((CMSIncrementalMode && _icms_disabled >= 0) || \214(!CMSIncrementalMode && _icms_disabled <= 0), "Error")215216static inline void enable_icms() {217ICMS_ENABLING_ASSERT;218Atomic::dec(&_icms_disabled);219}220static inline void disable_icms() {221ICMS_ENABLING_ASSERT;222Atomic::inc(&_icms_disabled);223}224static inline bool icms_is_disabled() {225ICMS_ENABLING_ASSERT;226return _icms_disabled > 0;227}228static inline bool icms_is_enabled() {229return !icms_is_disabled();230}231};232233inline void ConcurrentMarkSweepThread::trace_state(const char* desc) {234if (CMSTraceThreadState) {235char buf[128];236TimeStamp& ts = gclog_or_tty->time_stamp();237if (!ts.is_updated()) {238ts.update();239}240jio_snprintf(buf, sizeof(buf), " [%.3f: CMSThread %s] ",241ts.seconds(), desc);242buf[sizeof(buf) - 1] = '\0';243gclog_or_tty->print("%s", buf);244}245}246247// For scoped increment/decrement of (synchronous) yield requests248class CMSSynchronousYieldRequest: public StackObj {249public:250CMSSynchronousYieldRequest() {251ConcurrentMarkSweepThread::increment_pending_yields();252}253~CMSSynchronousYieldRequest() {254ConcurrentMarkSweepThread::decrement_pending_yields();255}256};257258// Used to emit a warning in case of unexpectedly excessive259// looping (in "apparently endless loops") in CMS code.260class CMSLoopCountWarn: public StackObj {261private:262const char* _src;263const char* _msg;264const intx _threshold;265intx _ticks;266267public:268inline CMSLoopCountWarn(const char* src, const char* msg,269const intx threshold) :270_src(src), _msg(msg), _threshold(threshold), _ticks(0) { }271272inline void tick() {273_ticks++;274if (CMSLoopWarn && _ticks % _threshold == 0) {275warning("%s has looped " INTX_FORMAT " times %s", _src, _ticks, _msg);276}277}278};279280#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPTHREAD_HPP281282283