8280844: Epoch shift synchronization point for Compiler threads is inadequate

Reviewed-by: egahlin
This commit is contained in:
Markus Grönlund 2022-05-18 09:06:14 +00:00
parent 44b243a061
commit d936c3024a
6 changed files with 16 additions and 88 deletions

View File

@ -739,7 +739,6 @@ public class GenerateJfrFiles {
out.write("#include \"utilities/ticks.hpp\"");
out.write("#if INCLUDE_JFR");
out.write("#include \"jfr/recorder/service/jfrEvent.hpp\"");
out.write("#include \"jfr/support/jfrEpochSynchronization.hpp\"");
out.write("/*");
out.write(" * Each event class has an assert member function verify() which is invoked");
out.write(" * just before the engine writes the event and its fields to the data stream.");
@ -869,10 +868,6 @@ public class GenerateJfrFiles {
if (type.isEvent && type.internal) {
out.write(" JfrEventSetting::unhide_internal_types();");
}
if (("_thread_in_native").equals(type.commitState)) {
out.write(" // explicit epoch synchronization check");
out.write(" JfrEpochSynchronization sync;");
}
for (FieldElement field : type.fields) {
if (field.struct) {
out.write(" _" + field.name + ".writeData(w);");

View File

@ -27,7 +27,9 @@
#include "jfr/jfr.hpp"
#include "jfr/jfrEvents.hpp"
#include "jfr/metadata/jfrSerializer.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/semaphore.inline.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/growableArray.hpp"
// Synchronizes access to phases_names.
@ -114,6 +116,16 @@ int CompilerEvent::PhaseEvent::get_phase_id(const char* phase_name, bool may_exi
return index;
}
// As part of event commit, a Method* is tagged as a function of an epoch.
// Epochs evolve during safepoints. To ensure the event is tagged in the correct epoch,
// that is, to avoid a race, the thread will participate in the safepoint protocol
// by transitioning from _thread_in_native to _thread_in_vm.
template <typename EventType>
static inline void commit(EventType& event) {
ThreadInVMfromNative transition(JavaThread::current());
event.commit();
}
void CompilerEvent::CompilationEvent::post(EventCompilation& event, int compile_id, CompilerType compiler_type, Method* method, int compile_level, bool success, bool is_osr, int code_size, int inlined_bytecodes) {
event.set_compileId(compile_id);
event.set_compiler(compiler_type);
@ -123,7 +135,7 @@ void CompilerEvent::CompilationEvent::post(EventCompilation& event, int compile_
event.set_isOsr(is_osr);
event.set_codeSize(code_size);
event.set_inlinedBytes(inlined_bytecodes);
event.commit();
commit(event);
}
void CompilerEvent::CompilationFailureEvent::post(EventCompilationFailure& event, int compile_id, const char* reason) {
@ -147,7 +159,7 @@ void CompilerEvent::InlineEvent::post(EventCompilerInlining& event, int compile_
event.set_succeeded(success);
event.set_message(msg);
event.set_bci(bci);
event.commit();
commit(event);
}
void CompilerEvent::InlineEvent::post(EventCompilerInlining& event, int compile_id, Method* caller, Method* callee, bool success, const char* msg, int bci) {

View File

@ -558,7 +558,7 @@
<Field type="ulong" contentType="bytes" name="used" label="Used" />
</Event>
<Event name="Compilation" category="Java Virtual Machine, Compiler" label="Compilation" thread="true" commitState="_thread_in_native">
<Event name="Compilation" category="Java Virtual Machine, Compiler" label="Compilation" thread="true">
<Field type="uint" name="compileId" label="Compilation Identifier" relation="CompileId" />
<Field type="CompilerType" name="compiler" label="Compiler" />
<Field type="Method" name="method" label="Method" />
@ -586,7 +586,7 @@
<Field type="string" name="descriptor" label="Method Descriptor" />
</Type>
<Event name="CompilerInlining" category="Java Virtual Machine, Compiler, Optimization" label="Method Inlining" thread="true" startTime="false" commitState="_thread_in_native">
<Event name="CompilerInlining" category="Java Virtual Machine, Compiler, Optimization" label="Method Inlining" thread="true" startTime="false">
<Field type="uint" name="compileId" label="Compilation Identifier" relation="CompileId" />
<Field type="Method" name="caller" label="Caller Method" />
<Field type="CalleeMethod" name="callee" struct="true" label="Callee Method" />

View File

@ -72,7 +72,6 @@
<xs:attribute name="period" type="periodType" use="optional" />
<xs:attribute name="cutoff" type="xs:boolean" use="optional" />
<xs:attribute name="throttle" type="xs:boolean" use="optional" />
<xs:attribute name="commitState" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
<xs:element maxOccurs="unbounded" name="Type">

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp"
#include "jfr/support/jfrEpochSynchronization.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/thread.inline.hpp"
JfrEpochSynchronization::JfrEpochSynchronization() {
if (JfrTraceIdEpoch::is_synchronizing()) {
// only at a safepoint
JavaThread* const jt = JavaThread::current();
assert(jt->thread_state() == _thread_in_native, "invariant");
// use ordinary transition to have the thread block and await the new epoch
ThreadInVMfromNative transition(jt);
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_JFR_SUPPORT_JFREPOCHSYNCHRONIZATION_HPP
#define SHARE_JFR_SUPPORT_JFREPOCHSYNCHRONIZATION_HPP
#include "jfr/support/jfrThreadId.hpp"
/*
* JavaThreads running _thread_in_native (Compiler threads) must synchronize
* with the upcoming epoch in case there is an epoch shift in-progress.
*/
class JfrEpochSynchronization {
public:
JfrEpochSynchronization();
};
#endif // SHARE_JFR_SUPPORT_JFREPOCHSYNCHRONIZATION_HPP