Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_realtime/MetronomeAlarmThread.cpp
5985 views
1
2
/*******************************************************************************
3
* Copyright (c) 1991, 2019 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* 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
22
*******************************************************************************/
23
24
/**
25
* @file
26
*/
27
28
#include "omrutil.h"
29
30
#include "MetronomeAlarmThread.hpp"
31
#include "MetronomeDelegate.hpp"
32
#include "OSInterface.hpp"
33
#include "RealtimeGC.hpp"
34
#include "Timer.hpp"
35
36
#if defined(LINUX)
37
#if !defined(J9ZTPF)
38
#include <sys/signal.h>
39
#include <linux/unistd.h>
40
#endif /* !defined(J9ZTPF) */
41
#include <sys/types.h>
42
#endif
43
44
45
MM_MetronomeAlarmThread *
46
MM_MetronomeAlarmThread::newInstance(MM_EnvironmentBase *env)
47
{
48
MM_MetronomeAlarmThread *alarmThread;
49
50
alarmThread = (MM_MetronomeAlarmThread *)env->getForge()->allocate(sizeof(MM_MetronomeAlarmThread), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE());
51
if (alarmThread) {
52
new(alarmThread) MM_MetronomeAlarmThread(env);
53
if (!alarmThread->initialize(env)) {
54
alarmThread->kill(env);
55
return NULL;
56
}
57
}
58
return alarmThread;
59
}
60
61
void
62
MM_MetronomeAlarmThread::kill(MM_EnvironmentBase *env)
63
{
64
tearDown(env);
65
env->getForge()->free(this);
66
}
67
68
void
69
MM_MetronomeAlarmThread::tearDown(MM_EnvironmentBase *env)
70
{
71
/* Shut down the alarm thread, if there is one running */
72
omrthread_monitor_enter(_mutex);
73
74
/* Set shutdown thread flag */
75
_shutdown = true;
76
77
while (_alarmThreadActive == ALARM_THREAD_ACTIVE) {
78
omrthread_monitor_wait(_mutex);
79
}
80
81
omrthread_monitor_exit(_mutex);
82
83
/* Kill the alarm only after the alarm thread is killed */
84
if (NULL != _alarm) {
85
_alarm->kill(env);
86
_alarm = NULL;
87
}
88
89
if (NULL != _mutex) {
90
omrthread_monitor_destroy(_mutex);
91
_mutex = NULL;
92
}
93
}
94
95
bool
96
MM_MetronomeAlarmThread::initialize(MM_EnvironmentBase *env)
97
{
98
if (0 != omrthread_monitor_init_with_name(&_mutex, 0, "Metronome Alarm Thread")) {
99
return false;
100
}
101
102
/* TODO: The MM_Alarm classes don't quite have the newInstance/initialize
103
* pattern right, so we have to manually call initialize.
104
*/
105
_alarm = MM_Alarm::factory(env, _scheduler->_osInterface);
106
if (!_alarm || !_alarm->initialize(env, this)) {
107
return false;
108
}
109
110
return true;
111
}
112
113
/**
114
* C entrypoint for the newly created alarm thread.
115
*/
116
int J9THREAD_PROC
117
MM_MetronomeAlarmThread::metronomeAlarmThreadWrapper(void* userData)
118
{
119
return MM_MetronomeDelegate::metronomeAlarmThreadWrapper(userData);
120
}
121
122
/**
123
* Fork a separate thread to perform the periodic alarms.
124
* Some may instantiate this class without actually calling this method
125
* to create a separate thread.
126
* @todo Clean up the abstraction so it makes a bit more sense. Probably
127
* merging most of the code in this class into MM_Alarm.
128
* @return true if the thread was successfully created, false otherwise
129
*/
130
bool
131
MM_MetronomeAlarmThread::startThread(MM_EnvironmentBase *env)
132
{
133
uintptr_t startPriority;
134
bool retCode;
135
136
startPriority = J9THREAD_PRIORITY_MAX;
137
138
if (J9THREAD_SUCCESS != createThreadWithCategory(
139
&_thread,
140
64 * 1024,
141
startPriority,
142
0,
143
MM_MetronomeAlarmThread::metronomeAlarmThreadWrapper,
144
this,
145
J9THREAD_CATEGORY_SYSTEM_GC_THREAD)) {
146
return false;
147
}
148
149
omrthread_monitor_enter(_mutex);
150
while (_alarmThreadActive == ALARM_THREAD_INACTIVE) {
151
omrthread_monitor_wait(_mutex);
152
}
153
retCode = (_alarmThreadActive == ALARM_THREAD_ACTIVE);
154
omrthread_monitor_exit(_mutex);
155
156
return retCode;
157
}
158
159
/**
160
* C++ entrypoint for the newly-created alarm thread.
161
*/
162
void
163
MM_MetronomeAlarmThread::run(MM_EnvironmentRealtime *env)
164
{
165
omrthread_monitor_enter(_mutex);
166
167
_alarmThreadActive = ALARM_THREAD_ACTIVE;
168
omrthread_monitor_notify(_mutex);
169
170
while (!_shutdown) {
171
omrthread_monitor_exit(_mutex);
172
173
_alarm->sleep();
174
175
if (env->getTimer()->hasTimeElapsed(_scheduler->getStartTimeOfCurrentMutatorSlice(), _scheduler->beatNanos)) {
176
_scheduler->continueGC(env, TIME_TRIGGER, 0, NULL, true);
177
}
178
179
omrthread_monitor_enter(_mutex);
180
}
181
omrthread_monitor_exit(_mutex);
182
}
183
184
185