Path: blob/master/runtime/gc_realtime/Scheduler.hpp
5985 views
/*******************************************************************************1* Copyright (c) 1991, 2020 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122/**23* @file24* @ingroup GC_Metronome25*/2627#if !defined(SCHEDULER_HPP_)28#define SCHEDULER_HPP_2930#include "omr.h"31#include "omrcfg.h"3233#include "Base.hpp"34#include "GCCode.hpp"35#include "GCExtensionsBase.hpp"36#include "Metronome.hpp"37#include "ParallelDispatcher.hpp"38#include "YieldCollaborator.hpp"3940class MM_OSInterface;41class MM_EnvironmentBase;42class MM_EnvironmentRealtime;43class MM_MemorySubSpaceMetronome;44class MM_Metronome;45class MM_RealtimeGC;46class MM_MetronomeAlarmThread;47class MM_Timer;48class MM_UtilizationTracker;4950#define METRONOME_GC_ON 151#define METRONOME_GC_OFF 05253/**54* @todo Provide class documentation55* @ingroup GC_Metronome56*/57class MM_Scheduler : public MM_ParallelDispatcher58{59/*60* Data members61*/62private:63U_64 _mutatorStartTimeInNanos; /**< Time in nanoseconds when the mutator slice started. This is updated at increment end and when a GC quantum is skipped due to shouldMutatorDoubleBeat */64U_64 _incrementStartTimeInNanos; /**< Time in nanoseconds when the last gc increment started */65MM_GCCode _gcCode; /**< The gc code that will be used for the next GC cycle. If this is modified during a collect it will be unused. This variable is reset at the end of every cycle to the default collection type */6667protected:68public:69bool _isInitialized; /**< Set to true when all threads have been started */70volatile uintptr_t _sharedBarrierState;7172MM_YieldCollaborator *_yieldCollaborator;7374/*75* Cached value for shouldGCYield()76*/77volatile bool _shouldGCYield;7879/* When utilization is over 50%, multiple consecutive GC beats is not allowed.80* Double-beating is allowed between 33% and 50% utilization and so on.81* We must keep track of the number of consecutive beats dynamically to ensure this.82*/83I_32 _currentConsecutiveBeats;8485bool *_threadResumedTable; /**< Used to keep track of threads taken out of the suspended state when wakeUpThreads is called */8687bool _mainThreadMustShutDown; /**< Set when the main thread must shutdown */8889bool _exclusiveVMAccessRequired; /**< This flag is used by the main thread to see if it needs to get exclusive vm access */9091MM_MetronomeAlarmThread *_alarmThread;92MM_EnvironmentRealtime *_threadWaitingOnMainThreadMonitor;93uintptr_t _mutatorCount;9495MM_RealtimeGC *_gc;96OMR_VM *_vm;97MM_GCExtensionsBase *_extensions;98bool _doSchedulingBarrierEvents;99100U_32 _gcOn; /* Are we in some long GC cycle? */101typedef enum {102MUTATOR = 0, /* main blocked on a monitor, mutators running */103WAKING_GC,104STOP_MUTATOR, /* main thread awake - waiting for mut threads to reach safe point */105AWAIT_GC, /* waiting for other gc threads to reach initial barrier */106RUNNING_GC,107WAKING_MUTATOR, /* main thread still awake, mutators running */108NUM_MODES109} Mode;110Mode _mode;111uintptr_t _gcPhaseSet;112/* requests (typically by a mutator) to complete GC synchronously */113bool _completeCurrentGCSynchronously;114/* copy of the request made by Main Thread at the beginning of very next GC increment */115bool _completeCurrentGCSynchronouslyMainThreadCopy;116GCReason _completeCurrentGCSynchronouslyReason;117uintptr_t _completeCurrentGCSynchronouslyReasonParameter;118/* monitor used to suspend/resume main thread,119* but also to ensure atomic access/change of _completeCurrentGCSynchronously/_mode */120omrthread_monitor_t _mainThreadMonitor;121122MM_OSInterface *_osInterface;123124/* Params generated from command-line options from mmparse */125double window;126double beat;127U_64 beatNanos;128double _staticTargetUtilization;129130MM_UtilizationTracker* _utilTracker;131132/*133* Function members134*/135private:136137protected:138/**139* Overrides of functionality in MM_ParallelDispatcher140* @{141*/142virtual uintptr_t getThreadPriority();143144/**145* @copydoc MM_ParallelDispatcher::useSeparateMainThread()146* Because Metronome requires all GC threads to begin an increment147* at the same location where they left off, it uses a separate148* thread as the GC main thread, instead of using one of the149* mutator threads.150*/151virtual bool useSeparateMainThread() { return true; }152153virtual void wakeUpThreads(uintptr_t count);154void wakeUpWorkerThreads(uintptr_t count);155156virtual void workerEntryPoint(MM_EnvironmentBase *env);157virtual void mainEntryPoint(MM_EnvironmentBase *env);158159bool internalShouldGCYield(MM_EnvironmentRealtime *env, U_64 timeSlack);160161/** @} */162163public:164void pushYieldCollaborator(MM_YieldCollaborator *yieldCollaborator) {165_yieldCollaborator = yieldCollaborator->push(_yieldCollaborator);166}167void popYieldCollaborator() {168_yieldCollaborator = _yieldCollaborator->pop();169}170171void shutDownWorkerThreads();172void shutDownMainThread();173void startGCIfTimeExpired(MM_EnvironmentBase *env);174175virtual bool condYieldFromGCWrapper(MM_EnvironmentBase *env, U_64 timeSlack = 0);176177uintptr_t incrementMutatorCount();178179uintptr_t getParameter(uintptr_t which, char *keyBuffer, I_32 keyBufferSize, char *valueBuffer, I_32 valueBufferSize);180void showParameters(MM_EnvironmentBase *env);181182/**183* Set scheduling parameters on argument extensions object to184* simulate Stop-The-World GC. We simulate STW by running time-based,185* with MMU, etc. parameters chosen so that the GC will not yield to the186* mutator until an entire GC cycle has completed.187*/188static void initializeForVirtualSTW(MM_GCExtensionsBase *ext);189190bool isInitialized() { return _isInitialized; }191192static MM_Scheduler *newInstance(MM_EnvironmentBase *env, omrsig_handler_fn handler, void* handler_arg, uintptr_t defaultOSStackSize);193bool initialize(MM_EnvironmentBase *env);194virtual void kill(MM_EnvironmentBase *env);195void tearDown(MM_EnvironmentBase *env);196197virtual bool startUpThreads();198virtual void shutDownThreads();199200virtual void prepareThreadsForTask(MM_EnvironmentBase *env, MM_Task *task, uintptr_t threadCount);201virtual void completeTask(MM_EnvironmentBase *env);202203void checkStartGC(MM_EnvironmentRealtime *env);204void startGC(MM_EnvironmentBase *env); /* Call when some space threshold is triggered. */205void stopGC(MM_EnvironmentBase *env);206bool isGCOn();207bool shouldGCDoubleBeat(MM_EnvironmentRealtime *env);208bool shouldMutatorDoubleBeat(MM_EnvironmentRealtime *env, MM_Timer *timer);209void reportStartGCIncrement(MM_EnvironmentRealtime *env);210void reportStopGCIncrement(MM_EnvironmentRealtime *env, bool isCycleEnd = false);211void restartMutatorsAndWait(MM_EnvironmentRealtime *env);212bool shouldGCYield(MM_EnvironmentRealtime *env, U_64 timeSlack);213bool condYieldFromGC(MM_EnvironmentBase *env, U_64 timeSlack = 0);214/* Low-level yielding from inside the Scheduler */215void yieldFromGC(MM_EnvironmentRealtime *env, bool distanceChecked = false);216void waitForMutatorsToStop(MM_EnvironmentRealtime *env);217void startMutators(MM_EnvironmentRealtime *env);218bool continueGC(MM_EnvironmentRealtime *, GCReason reason, uintptr_t reasonParameter, OMR_VMThread *_vmThread, bool doRequestExclusiveVMAccess); /* Non-blocking and typicallly called by an alarm handler. Returns 1 if we did resume GC (non-recursive). */219void setGCPriority(MM_EnvironmentBase *env, uintptr_t priority); /* sets the priority for all gc threads */220void completeCurrentGCSynchronously(MM_EnvironmentRealtime *env = NULL);221222uintptr_t verbose() { return _extensions->verbose; }223uintptr_t debug() { return _extensions->debug; }224225virtual void recomputeActiveThreadCount(MM_EnvironmentBase *env);226227/* Time and Work Statistics */228void startGCTime(MM_EnvironmentRealtime *env, bool isDoubleBeat);229void stopGCTime(MM_EnvironmentRealtime *env);230U_64 getStartTimeOfCurrentMutatorSlice() {return _mutatorStartTimeInNanos;}231void setStartTimeOfCurrentMutatorSlice(U_64 time) {_mutatorStartTimeInNanos = time;}232U_64 getStartTimeOfCurrentGCSlice() {return _incrementStartTimeInNanos;}233void setStartTimeOfCurrentGCSlice(U_64 time) {_incrementStartTimeInNanos = time;}234235uintptr_t getActiveThreadCount() { return _activeThreadCount; }236uintptr_t getTaskThreadCount(MM_EnvironmentBase *env);237void setGCCode(MM_GCCode gcCode) {_gcCode = gcCode;}238239void collectorInitialized(MM_RealtimeGC *gc);240241MM_Scheduler(MM_EnvironmentBase *env, omrsig_handler_fn handler, void* handler_arg, uintptr_t defaultOSStackSize) :242MM_ParallelDispatcher(env, handler, handler_arg, defaultOSStackSize),243_mutatorStartTimeInNanos(J9CONST64(0)),244_incrementStartTimeInNanos(J9CONST64(0)),245_gcCode(J9MMCONSTANT_IMPLICIT_GC_DEFAULT),246_isInitialized(false),247_yieldCollaborator(NULL),248_shouldGCYield(false),249_currentConsecutiveBeats(0),250_threadResumedTable(NULL),251_mainThreadMustShutDown(false),252_exclusiveVMAccessRequired(true),253_alarmThread(NULL),254_threadWaitingOnMainThreadMonitor(NULL),255_mutatorCount(0),256_gc(NULL),257_vm(env->getOmrVM()),258_extensions(MM_GCExtensionsBase::getExtensions(_vm)),259_doSchedulingBarrierEvents(false),260_gcOn(METRONOME_GC_OFF),261_mode(MUTATOR),262_gcPhaseSet(GC_PHASE_IDLE),263_completeCurrentGCSynchronously(false),264_completeCurrentGCSynchronouslyMainThreadCopy(false),265_completeCurrentGCSynchronouslyReason(UNKOWN_REASON),266_completeCurrentGCSynchronouslyReasonParameter(0),267_mainThreadMonitor(NULL),268_osInterface(NULL),269window(),270beat(),271beatNanos(),272_staticTargetUtilization(),273_utilTracker(NULL)274{275_typeId = __FUNCTION__;276}277278/*279* Friends280*/281friend class MM_EnvironmentRealtime;282};283284#endif /* SCHEDULER_HPP_ */285286287288