Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_realtime/MetronomeAlarm.cpp
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2019 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
#include "EnvironmentBase.hpp"
24
#include "MetronomeAlarmThread.hpp"
25
#include "OSInterface.hpp"
26
#include "Scheduler.hpp"
27
28
#include "MetronomeAlarm.hpp"
29
30
#if defined(LINUX)
31
#include <time.h>
32
#include <errno.h>
33
#include <sys/time.h>
34
#include <sys/mman.h>
35
#include <sched.h>
36
#include <unistd.h>
37
#include <sys/types.h>
38
#include <sys/stat.h>
39
#include <fcntl.h>
40
#include <sys/ioctl.h>
41
#include <netdb.h>
42
#include <sys/socket.h>
43
#include <sys/types.h>
44
#include <net/if.h>
45
#include <netdb.h>
46
#include <netinet/in.h>
47
#include <arpa/inet.h>
48
#endif /* #if defined(LINUX) */
49
#if defined(LINUX) && !defined(J9ZTPF)
50
#include <linux/rtc.h>
51
#include <sys/syscall.h>
52
#include <sys/signal.h>
53
#elif defined(J9ZTPF)
54
#include <signal.h>
55
#endif /* defined(LINUX) && !defined(J9ZTPF) */
56
57
MM_HRTAlarm *
58
MM_HRTAlarm::newInstance(MM_EnvironmentBase *env)
59
{
60
MM_HRTAlarm * alarm;
61
62
alarm = (MM_HRTAlarm *)env->getForge()->allocate(sizeof(MM_HRTAlarm), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE());
63
if (alarm) {
64
new(alarm) MM_HRTAlarm();
65
}
66
return alarm;
67
}
68
69
MM_RTCAlarm *
70
MM_RTCAlarm::newInstance(MM_EnvironmentBase *env)
71
{
72
MM_RTCAlarm * alarm;
73
74
alarm = (MM_RTCAlarm *)env->getForge()->allocate(sizeof(MM_RTCAlarm), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE());
75
if (alarm) {
76
new(alarm) MM_RTCAlarm();
77
}
78
return alarm;
79
}
80
81
MM_ITAlarm *
82
MM_ITAlarm::newInstance(MM_EnvironmentBase *env)
83
{
84
MM_ITAlarm * alarm;
85
86
alarm = (MM_ITAlarm *)env->getForge()->allocate(sizeof(MM_ITAlarm), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE());
87
if (alarm) {
88
new(alarm) MM_ITAlarm();
89
}
90
return alarm;
91
}
92
93
/**
94
* MM_Alarm::newInstance - create a new alarm suitable for the system.
95
*/
96
MM_Alarm*
97
MM_Alarm::factory(MM_EnvironmentBase *env, MM_OSInterface* osInterface)
98
{
99
MM_Alarm *alarm = NULL;
100
101
if (osInterface->hiresTimerAvailable()) {
102
alarm = MM_HRTAlarm::newInstance(env);
103
} else if (osInterface->itTimerAvailable()) {
104
alarm = MM_ITAlarm::newInstance(env);
105
}
106
return alarm;
107
}
108
109
110
/**
111
* initialize
112
* Initialize the High Resolution Timer for use by Metronome.
113
* @return true if the high resolution timer was successfully initialized, false
114
* otherwise
115
*/
116
bool
117
MM_HRTAlarm::initialize(MM_EnvironmentBase *env, MM_MetronomeAlarmThread* alarmThread)
118
{
119
_extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM());
120
return alarmThread->startThread(env);
121
}
122
123
/**
124
* initialize
125
* Initialize the Linux real-time clock for use by Metronome. On
126
* non-Linux OS's, it is an error to be working with RTCAlarm's
127
* This code has OS-specific code in it, but it will disappear in time
128
* when we have HRT Alarm's running everywhere...
129
* @return true if the real-time clock was successfully initialized, false
130
* otherwise
131
*/
132
133
bool
134
MM_RTCAlarm::initialize(MM_EnvironmentBase *env, MM_MetronomeAlarmThread* alarmThread)
135
{
136
_extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM());
137
#if defined(LINUX) && !defined(J9ZTPF)
138
OMRPORT_ACCESS_FROM_ENVIRONMENT(env);
139
140
RTCfd = open("/dev/rtc", O_RDONLY);
141
if (RTCfd == -1) {
142
if (_extensions->verbose >= 2) {
143
omrtty_printf("Unable to open /dev/rtc\n");
144
}
145
goto error;
146
}
147
if ((ioctl(RTCfd, RTC_IRQP_SET, _extensions->RTC_Frequency) == -1)) {
148
if (_extensions->verbose >= 2) {
149
omrtty_printf("Unable to set IRQP for /dev/rtc\n");
150
}
151
goto error;
152
}
153
if (ioctl(RTCfd, RTC_IRQP_READ, &_extensions->RTC_Frequency)) {
154
if (_extensions->verbose >= 2) {
155
omrtty_printf("Unable to read IRQP for /dev/rtc\n");
156
}
157
goto error;
158
}
159
if (ioctl(RTCfd, RTC_PIE_ON, 0) == -1) {
160
if (_extensions->verbose >= 2) {
161
omrtty_printf("Unable to enable PIE for /dev/rtc\n");
162
}
163
goto error;
164
}
165
166
return alarmThread->startThread(env);
167
168
error:
169
if (_extensions->verbose >= 1) {
170
omrtty_printf("Unable to use /dev/rtc for time-based scheduling\n");
171
}
172
return false;
173
#else
174
return false;
175
#endif /* defined(LINUX) && !defined(J9ZTPF) */
176
}
177
178
void MM_ITAlarm::alarm_handler(MM_MetronomeAlarmThread *alarmThread) {
179
MM_Scheduler *sched = alarmThread->getScheduler();
180
sched->_osInterface->maskSignals();
181
omrthread_resume(alarmThread->_thread);
182
}
183
184
#if defined(WIN32)
185
static void CALLBACK
186
itAlarmThunk(PVOID lpParam, BOOLEAN timerOrWaitFired)
187
{
188
MM_ITAlarm::alarm_handler((MM_MetronomeAlarmThread *)lpParam);
189
}
190
#endif /*WIN32*/
191
192
193
/**
194
* Initialize the interval timer alarm. This timer is not
195
* used except as a backup if HRT and RTC alarms aren't available.
196
* This code has OS-specific code in it, but it will disappear in time
197
* when we have HRT Alarm's running everywhere...
198
* @return true if the real-time clock was successfully initialized, false
199
* otherwise
200
*/
201
bool
202
MM_ITAlarm::initialize(MM_EnvironmentBase *env, MM_MetronomeAlarmThread* alarmThread)
203
{
204
_extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM());
205
if (!alarmThread->startThread(env)) {
206
return false;
207
}
208
209
#if defined(WIN32)
210
DWORD dwPeriod = (DWORD)(_extensions->itPeriodMicro / 1000);
211
DWORD dwDelay = dwPeriod;
212
BOOL ret = CreateTimerQueueTimer(&_hTimer, NULL, (WAITORTIMERCALLBACK)itAlarmThunk, (PVOID)alarmThread, dwDelay, dwPeriod, 0);
213
if (!ret) {
214
/* Error creating timer */
215
_hTimer = NULL;
216
return false;
217
}
218
219
return true;
220
#else /* !defined(WIN32)*/
221
/* write code if we want this path on other platforms */
222
return false;
223
#endif /* defined(WIN32) */
224
}
225
226
void
227
MM_RTCAlarm::sleep()
228
{
229
#if defined(LINUX) && !defined(J9ZTPF)
230
uintptr_t data;
231
ssize_t readAmount = read(RTCfd, &data, sizeof(data));
232
if (readAmount == -1) {
233
perror("blocking read failed");
234
}
235
#endif /* defined(LINUX) && !defined(J9ZTPF) */
236
}
237
238
void
239
MM_HRTAlarm::sleep()
240
{
241
omrthread_nanosleep(_extensions->hrtPeriodMicro * 1000);
242
}
243
244
void
245
MM_ITAlarm::sleep()
246
{
247
omrthread_suspend();
248
}
249
250
void MM_RTCAlarm::describe(OMRPortLibrary* port, char *buffer, I_32 bufferSize) {
251
OMRPORT_ACCESS_FROM_OMRPORT(port);
252
omrstr_printf(buffer, bufferSize, "RTC (Period = %.2f us Frequency = %d Hz)", 1.0/_extensions->RTC_Frequency, _extensions->RTC_Frequency);
253
}
254
255
void MM_HRTAlarm::describe(OMRPortLibrary* port, char *buffer, I_32 bufferSize) {
256
OMRPORT_ACCESS_FROM_OMRPORT(port);
257
omrstr_printf(buffer, bufferSize, "High Resolution Timer (Period = %d us)", _extensions->hrtPeriodMicro);
258
}
259
260
void MM_ITAlarm::describe(OMRPortLibrary* port, char *buffer, I_32 bufferSize) {
261
OMRPORT_ACCESS_FROM_OMRPORT(port);
262
omrstr_printf(buffer, bufferSize, "Interval Timer (Period = %d us)", _extensions->itPeriodMicro);
263
}
264
265
/**
266
* kill
267
* teardown the environment and free up storage associated with the object
268
*/
269
void
270
MM_Alarm::kill(MM_EnvironmentBase *env)
271
{
272
tearDown(env);
273
env->getForge()->free(this);
274
}
275
276
/**
277
* tearDown
278
*/
279
void
280
MM_Alarm::tearDown(MM_EnvironmentBase *env)
281
{
282
}
283
284
/**
285
* tearDown
286
*/
287
void
288
MM_ITAlarm::tearDown(MM_EnvironmentBase *env)
289
{
290
#if defined(WIN32)
291
if (NULL != _hTimer) {
292
DeleteTimerQueueTimer(NULL, _hTimer, NULL);
293
}
294
#endif /* defined(WIN32) */
295
MM_Alarm::tearDown(env);
296
}
297
298