Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/infra/J9MonitorTable.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2021 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 "infra/MonitorTable.hpp"
24
#include "infra/Monitor.hpp"
25
#include "infra/CriticalSection.hpp"
26
#include "control/CompilationRuntime.hpp"
27
28
#include "j9.h"
29
#include "j9cfg.h"
30
#include "j9thread.h"
31
#include "j9port.h"
32
33
34
// allocated during codert_onload
35
TR::MonitorTable *
36
J9::MonitorTable::init(
37
J9PortLibrary *portLib,
38
J9JavaVM *javaVM)
39
{
40
if (_instance)
41
{
42
return _instance;
43
}
44
45
PORT_ACCESS_FROM_PORT(portLib);
46
void *tableMem = j9mem_allocate_memory(sizeof(TR::MonitorTable), J9MEM_CATEGORY_JIT);
47
if (!tableMem) return 0;
48
TR::MonitorTable *table = new (tableMem) TR::MonitorTable();
49
50
table->_portLib = portLib;
51
table->_monitors.setFirst(0);
52
53
table->_numCompThreads = 0;
54
// Memory for classUnloadMonitorHolders will be allocated later in allocInitClassUnloadMonitorHolders()
55
// just before the compilation threads are started
56
table->_classUnloadMonitorHolders = NULL;
57
58
// Initialize the Monitors
59
if (!table->_tableMonitor.init("JIT-MonitorTableMonitor")) return 0;
60
if (!table->_j9ScratchMemoryPoolMonitor.init("JIT-ScratchMemoryPoolMonitor")) return 0;
61
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
62
if (!table->_classUnloadMonitor.initFromVMMutex(javaVM->classUnloadMutex)) return 0;
63
#else
64
if (!table->_classUnloadMonitor.init("JIT-ClassUnloadMonitor")) return 0;
65
#endif
66
if (!table->_iprofilerPersistenceMonitor.init("JIT-IProfilerPersistenceMonitor")) return 0;
67
68
// Setup a wrapper for VM's monitors that the JIT can acquire
69
if (!table->_classTableMutex.initFromVMMutex(javaVM->classTableMutex)) return 0;
70
71
table->_scratchMemoryPoolMonitor = &table->_j9ScratchMemoryPoolMonitor; // export this value
72
73
OMR::MonitorTable::_instance = table;
74
return table;
75
}
76
77
bool
78
J9::MonitorTable::allocInitClassUnloadMonitorHolders(uint32_t allowedTotalCompThreads)
79
{
80
PORT_ACCESS_FROM_PORT(_portLib);
81
82
_numCompThreads = allowedTotalCompThreads;
83
// Allocate and initialize the array of classUnloadMonitorHolders
84
_classUnloadMonitorHolders = (int32_t*)j9mem_allocate_memory(sizeof(*(_classUnloadMonitorHolders)) * _numCompThreads, J9MEM_CATEGORY_JIT);
85
if (!_classUnloadMonitorHolders)
86
return false;
87
for (int32_t i = 0; i < _numCompThreads; i++)
88
_classUnloadMonitorHolders[i] = 0;
89
90
return true;
91
}
92
93
TR::Monitor *
94
J9::MonitorTable::create(char *name)
95
{
96
PORT_ACCESS_FROM_PORT(_portLib);
97
98
void *monMem = j9mem_allocate_memory(sizeof(TR::Monitor), J9MEM_CATEGORY_JIT);
99
if (!monMem)
100
{
101
return 0;
102
}
103
104
TR::Monitor *m = new (monMem) TR::Monitor();
105
if (!m->init(name))
106
{
107
return 0;
108
}
109
110
//fprintf(stderr, "ADDING MONITOR: %p, %s (first is %p)\n", m, name, _monitors.getFirst());
111
self()->insert(m);
112
return m;
113
}
114
115
116
void
117
J9::MonitorTable::insert(TR::Monitor *monitor)
118
{
119
OMR::CriticalSection insertingNewMonitor(&_tableMonitor);
120
monitor->setNext(_monitors.getFirst());
121
_monitors.setFirst(monitor);
122
}
123
124
125
void
126
J9::MonitorTable::removeAndDestroy(TR::Monitor *monitor)
127
{
128
TR::MonitorTable *table = TR::MonitorTable::get();
129
if (!table) return;
130
PORT_ACCESS_FROM_PORT(table->_portLib);
131
// search the table for my monitor
132
{
133
OMR::CriticalSection searchTableAndRemoveMonitor(&_tableMonitor);
134
TR::Monitor *prevMonitor = NULL;
135
TR::Monitor *crtMonitor = (TR::Monitor *)table->_monitors.getFirst();
136
while (crtMonitor)
137
{
138
if (crtMonitor == monitor)
139
break;
140
prevMonitor = crtMonitor;
141
crtMonitor = crtMonitor->getNext();
142
}
143
if (crtMonitor)
144
{
145
// I found my monitor, so take it out from the link list
146
if (prevMonitor)
147
prevMonitor->setNext(crtMonitor->getNext());
148
else
149
table->_monitors.setFirst(crtMonitor->getNext());
150
crtMonitor->destroy();
151
// free the memory
152
j9mem_free_memory(monitor);
153
}
154
}
155
}
156
157
158
// Note that the following method does not destroys the actual monitors
159
// If we do, we must make sure that the monitors created from VM mutex are not destroyed
160
void
161
J9::MonitorTable::free()
162
{
163
TR::MonitorTable *table = TR::MonitorTable::get();
164
if (!table) return;
165
166
PORT_ACCESS_FROM_PORT(table->_portLib);
167
168
TR::Monitor *monitor = (TR::Monitor *)table->_monitors.getFirst();
169
while (monitor)
170
{
171
TR::Monitor *next = monitor->getNext();
172
j9mem_free_memory(monitor);
173
monitor = next;
174
}
175
j9mem_free_memory(table->_classUnloadMonitorHolders);
176
_instance = 0;
177
j9mem_free_memory(table);
178
};
179
180
181
// Used to check if current thread holds any known monitors
182
bool
183
J9::MonitorTable::isThreadInSafeMonitorState(J9VMThread *vmThread)
184
{
185
// If we hold any of the following locks, return failure.
186
if (_tableMonitor.owned_by_self() ||
187
_j9ScratchMemoryPoolMonitor.owned_by_self() ||
188
_classTableMutex.owned_by_self() ||
189
_iprofilerPersistenceMonitor.owned_by_self()
190
)
191
return false;
192
{
193
OMR::CriticalSection walkingMonitorTable(&_tableMonitor);
194
for (TR::Monitor *monitor = (TR::Monitor *)_monitors.getFirst(); monitor; monitor = monitor->getNext())
195
{
196
if (monitor->owned_by_self())
197
{
198
return false;
199
}
200
}
201
return true;
202
}
203
}
204
205
206
// Return the address of the first monitor that is found locked
207
TR::Monitor *
208
J9::MonitorTable::monitorHeldByCurrentThread()
209
{
210
// If we hold any of the following locks, return failure.
211
if (_tableMonitor.owned_by_self())
212
return &_tableMonitor;
213
if (_j9ScratchMemoryPoolMonitor.owned_by_self())
214
return &_j9ScratchMemoryPoolMonitor;
215
if (_classTableMutex.owned_by_self())
216
return &_classTableMutex;
217
if (_iprofilerPersistenceMonitor.owned_by_self())
218
return &_iprofilerPersistenceMonitor;
219
{
220
OMR::CriticalSection walkMonitorTable(&_tableMonitor);
221
for (TR::Monitor *monitor = (TR::Monitor *)_monitors.getFirst(); monitor; monitor = monitor->getNext())
222
{
223
if (monitor->owned_by_self())
224
{
225
return monitor;
226
}
227
}
228
}
229
return NULL;
230
}
231
232
233
int32_t
234
J9::MonitorTable::readAcquireClassUnloadMonitor(int32_t compThreadIndex)
235
{
236
_classUnloadMonitor.enter_read();
237
// Need to determine the identity of the compilation thread
238
TR_ASSERT(compThreadIndex < _numCompThreads, "compThreadIndex is too high");
239
return ++(_classUnloadMonitorHolders[compThreadIndex]);
240
}
241
242
243
int32_t
244
J9::MonitorTable::readReleaseClassUnloadMonitor(int32_t compThreadIndex)
245
{
246
TR_ASSERT(compThreadIndex < _numCompThreads, "compThreadIndex is too high");
247
if (_classUnloadMonitorHolders[compThreadIndex] > 0)
248
{
249
_classUnloadMonitorHolders[compThreadIndex]--;
250
_classUnloadMonitor.exit_read();
251
return _classUnloadMonitorHolders[compThreadIndex];
252
}
253
else
254
{
255
TR_ASSERT(false, "comp thread %d does not have classUnloadMonitor", compThreadIndex);
256
return -1; // could not release monitor
257
}
258
}
259
260