Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_realtime/Scheduler.hpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2020 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
23
/**
24
* @file
25
* @ingroup GC_Metronome
26
*/
27
28
#if !defined(SCHEDULER_HPP_)
29
#define SCHEDULER_HPP_
30
31
#include "omr.h"
32
#include "omrcfg.h"
33
34
#include "Base.hpp"
35
#include "GCCode.hpp"
36
#include "GCExtensionsBase.hpp"
37
#include "Metronome.hpp"
38
#include "ParallelDispatcher.hpp"
39
#include "YieldCollaborator.hpp"
40
41
class MM_OSInterface;
42
class MM_EnvironmentBase;
43
class MM_EnvironmentRealtime;
44
class MM_MemorySubSpaceMetronome;
45
class MM_Metronome;
46
class MM_RealtimeGC;
47
class MM_MetronomeAlarmThread;
48
class MM_Timer;
49
class MM_UtilizationTracker;
50
51
#define METRONOME_GC_ON 1
52
#define METRONOME_GC_OFF 0
53
54
/**
55
* @todo Provide class documentation
56
* @ingroup GC_Metronome
57
*/
58
class MM_Scheduler : public MM_ParallelDispatcher
59
{
60
/*
61
* Data members
62
*/
63
private:
64
U_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 */
65
U_64 _incrementStartTimeInNanos; /**< Time in nanoseconds when the last gc increment started */
66
MM_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 */
67
68
protected:
69
public:
70
bool _isInitialized; /**< Set to true when all threads have been started */
71
volatile uintptr_t _sharedBarrierState;
72
73
MM_YieldCollaborator *_yieldCollaborator;
74
75
/*
76
* Cached value for shouldGCYield()
77
*/
78
volatile bool _shouldGCYield;
79
80
/* When utilization is over 50%, multiple consecutive GC beats is not allowed.
81
* Double-beating is allowed between 33% and 50% utilization and so on.
82
* We must keep track of the number of consecutive beats dynamically to ensure this.
83
*/
84
I_32 _currentConsecutiveBeats;
85
86
bool *_threadResumedTable; /**< Used to keep track of threads taken out of the suspended state when wakeUpThreads is called */
87
88
bool _mainThreadMustShutDown; /**< Set when the main thread must shutdown */
89
90
bool _exclusiveVMAccessRequired; /**< This flag is used by the main thread to see if it needs to get exclusive vm access */
91
92
MM_MetronomeAlarmThread *_alarmThread;
93
MM_EnvironmentRealtime *_threadWaitingOnMainThreadMonitor;
94
uintptr_t _mutatorCount;
95
96
MM_RealtimeGC *_gc;
97
OMR_VM *_vm;
98
MM_GCExtensionsBase *_extensions;
99
bool _doSchedulingBarrierEvents;
100
101
U_32 _gcOn; /* Are we in some long GC cycle? */
102
typedef enum {
103
MUTATOR = 0, /* main blocked on a monitor, mutators running */
104
WAKING_GC,
105
STOP_MUTATOR, /* main thread awake - waiting for mut threads to reach safe point */
106
AWAIT_GC, /* waiting for other gc threads to reach initial barrier */
107
RUNNING_GC,
108
WAKING_MUTATOR, /* main thread still awake, mutators running */
109
NUM_MODES
110
} Mode;
111
Mode _mode;
112
uintptr_t _gcPhaseSet;
113
/* requests (typically by a mutator) to complete GC synchronously */
114
bool _completeCurrentGCSynchronously;
115
/* copy of the request made by Main Thread at the beginning of very next GC increment */
116
bool _completeCurrentGCSynchronouslyMainThreadCopy;
117
GCReason _completeCurrentGCSynchronouslyReason;
118
uintptr_t _completeCurrentGCSynchronouslyReasonParameter;
119
/* monitor used to suspend/resume main thread,
120
* but also to ensure atomic access/change of _completeCurrentGCSynchronously/_mode */
121
omrthread_monitor_t _mainThreadMonitor;
122
123
MM_OSInterface *_osInterface;
124
125
/* Params generated from command-line options from mmparse */
126
double window;
127
double beat;
128
U_64 beatNanos;
129
double _staticTargetUtilization;
130
131
MM_UtilizationTracker* _utilTracker;
132
133
/*
134
* Function members
135
*/
136
private:
137
138
protected:
139
/**
140
* Overrides of functionality in MM_ParallelDispatcher
141
* @{
142
*/
143
virtual uintptr_t getThreadPriority();
144
145
/**
146
* @copydoc MM_ParallelDispatcher::useSeparateMainThread()
147
* Because Metronome requires all GC threads to begin an increment
148
* at the same location where they left off, it uses a separate
149
* thread as the GC main thread, instead of using one of the
150
* mutator threads.
151
*/
152
virtual bool useSeparateMainThread() { return true; }
153
154
virtual void wakeUpThreads(uintptr_t count);
155
void wakeUpWorkerThreads(uintptr_t count);
156
157
virtual void workerEntryPoint(MM_EnvironmentBase *env);
158
virtual void mainEntryPoint(MM_EnvironmentBase *env);
159
160
bool internalShouldGCYield(MM_EnvironmentRealtime *env, U_64 timeSlack);
161
162
/** @} */
163
164
public:
165
void pushYieldCollaborator(MM_YieldCollaborator *yieldCollaborator) {
166
_yieldCollaborator = yieldCollaborator->push(_yieldCollaborator);
167
}
168
void popYieldCollaborator() {
169
_yieldCollaborator = _yieldCollaborator->pop();
170
}
171
172
void shutDownWorkerThreads();
173
void shutDownMainThread();
174
void startGCIfTimeExpired(MM_EnvironmentBase *env);
175
176
virtual bool condYieldFromGCWrapper(MM_EnvironmentBase *env, U_64 timeSlack = 0);
177
178
uintptr_t incrementMutatorCount();
179
180
uintptr_t getParameter(uintptr_t which, char *keyBuffer, I_32 keyBufferSize, char *valueBuffer, I_32 valueBufferSize);
181
void showParameters(MM_EnvironmentBase *env);
182
183
/**
184
* Set scheduling parameters on argument extensions object to
185
* simulate Stop-The-World GC. We simulate STW by running time-based,
186
* with MMU, etc. parameters chosen so that the GC will not yield to the
187
* mutator until an entire GC cycle has completed.
188
*/
189
static void initializeForVirtualSTW(MM_GCExtensionsBase *ext);
190
191
bool isInitialized() { return _isInitialized; }
192
193
static MM_Scheduler *newInstance(MM_EnvironmentBase *env, omrsig_handler_fn handler, void* handler_arg, uintptr_t defaultOSStackSize);
194
bool initialize(MM_EnvironmentBase *env);
195
virtual void kill(MM_EnvironmentBase *env);
196
void tearDown(MM_EnvironmentBase *env);
197
198
virtual bool startUpThreads();
199
virtual void shutDownThreads();
200
201
virtual void prepareThreadsForTask(MM_EnvironmentBase *env, MM_Task *task, uintptr_t threadCount);
202
virtual void completeTask(MM_EnvironmentBase *env);
203
204
void checkStartGC(MM_EnvironmentRealtime *env);
205
void startGC(MM_EnvironmentBase *env); /* Call when some space threshold is triggered. */
206
void stopGC(MM_EnvironmentBase *env);
207
bool isGCOn();
208
bool shouldGCDoubleBeat(MM_EnvironmentRealtime *env);
209
bool shouldMutatorDoubleBeat(MM_EnvironmentRealtime *env, MM_Timer *timer);
210
void reportStartGCIncrement(MM_EnvironmentRealtime *env);
211
void reportStopGCIncrement(MM_EnvironmentRealtime *env, bool isCycleEnd = false);
212
void restartMutatorsAndWait(MM_EnvironmentRealtime *env);
213
bool shouldGCYield(MM_EnvironmentRealtime *env, U_64 timeSlack);
214
bool condYieldFromGC(MM_EnvironmentBase *env, U_64 timeSlack = 0);
215
/* Low-level yielding from inside the Scheduler */
216
void yieldFromGC(MM_EnvironmentRealtime *env, bool distanceChecked = false);
217
void waitForMutatorsToStop(MM_EnvironmentRealtime *env);
218
void startMutators(MM_EnvironmentRealtime *env);
219
bool 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). */
220
void setGCPriority(MM_EnvironmentBase *env, uintptr_t priority); /* sets the priority for all gc threads */
221
void completeCurrentGCSynchronously(MM_EnvironmentRealtime *env = NULL);
222
223
uintptr_t verbose() { return _extensions->verbose; }
224
uintptr_t debug() { return _extensions->debug; }
225
226
virtual void recomputeActiveThreadCount(MM_EnvironmentBase *env);
227
228
/* Time and Work Statistics */
229
void startGCTime(MM_EnvironmentRealtime *env, bool isDoubleBeat);
230
void stopGCTime(MM_EnvironmentRealtime *env);
231
U_64 getStartTimeOfCurrentMutatorSlice() {return _mutatorStartTimeInNanos;}
232
void setStartTimeOfCurrentMutatorSlice(U_64 time) {_mutatorStartTimeInNanos = time;}
233
U_64 getStartTimeOfCurrentGCSlice() {return _incrementStartTimeInNanos;}
234
void setStartTimeOfCurrentGCSlice(U_64 time) {_incrementStartTimeInNanos = time;}
235
236
uintptr_t getActiveThreadCount() { return _activeThreadCount; }
237
uintptr_t getTaskThreadCount(MM_EnvironmentBase *env);
238
void setGCCode(MM_GCCode gcCode) {_gcCode = gcCode;}
239
240
void collectorInitialized(MM_RealtimeGC *gc);
241
242
MM_Scheduler(MM_EnvironmentBase *env, omrsig_handler_fn handler, void* handler_arg, uintptr_t defaultOSStackSize) :
243
MM_ParallelDispatcher(env, handler, handler_arg, defaultOSStackSize),
244
_mutatorStartTimeInNanos(J9CONST64(0)),
245
_incrementStartTimeInNanos(J9CONST64(0)),
246
_gcCode(J9MMCONSTANT_IMPLICIT_GC_DEFAULT),
247
_isInitialized(false),
248
_yieldCollaborator(NULL),
249
_shouldGCYield(false),
250
_currentConsecutiveBeats(0),
251
_threadResumedTable(NULL),
252
_mainThreadMustShutDown(false),
253
_exclusiveVMAccessRequired(true),
254
_alarmThread(NULL),
255
_threadWaitingOnMainThreadMonitor(NULL),
256
_mutatorCount(0),
257
_gc(NULL),
258
_vm(env->getOmrVM()),
259
_extensions(MM_GCExtensionsBase::getExtensions(_vm)),
260
_doSchedulingBarrierEvents(false),
261
_gcOn(METRONOME_GC_OFF),
262
_mode(MUTATOR),
263
_gcPhaseSet(GC_PHASE_IDLE),
264
_completeCurrentGCSynchronously(false),
265
_completeCurrentGCSynchronouslyMainThreadCopy(false),
266
_completeCurrentGCSynchronouslyReason(UNKOWN_REASON),
267
_completeCurrentGCSynchronouslyReasonParameter(0),
268
_mainThreadMonitor(NULL),
269
_osInterface(NULL),
270
window(),
271
beat(),
272
beatNanos(),
273
_staticTargetUtilization(),
274
_utilTracker(NULL)
275
{
276
_typeId = __FUNCTION__;
277
}
278
279
/*
280
* Friends
281
*/
282
friend class MM_EnvironmentRealtime;
283
};
284
285
#endif /* SCHEDULER_HPP_ */
286
287
288