8245113: JFR Recorder Thread to run in thread state "_thread_in_native"
Reviewed-by: egahlin
This commit is contained in:
parent
b9ce3b435e
commit
0228a5c767
src/hotspot/share/jfr
jni
leakprofiler/checkpoint
recorder
checkpoint
repository
service
utilities
@ -723,18 +723,20 @@ static bool check_exclusion_state_on_thread_start(JavaThread* jt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
jlong JfrJavaSupport::jfr_thread_id(jobject thread) {
|
||||
static JavaThread* get_native(jobject thread) {
|
||||
ThreadsListHandle tlh;
|
||||
JavaThread* native_thread = NULL;
|
||||
(void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL);
|
||||
return native_thread;
|
||||
}
|
||||
|
||||
jlong JfrJavaSupport::jfr_thread_id(jobject thread) {
|
||||
JavaThread* native_thread = get_native(thread);
|
||||
return native_thread != NULL ? JFR_THREAD_ID(native_thread) : 0;
|
||||
}
|
||||
|
||||
void JfrJavaSupport::exclude(jobject thread) {
|
||||
HandleMark hm;
|
||||
ThreadsListHandle tlh;
|
||||
JavaThread* native_thread = NULL;
|
||||
(void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL);
|
||||
JavaThread* native_thread = get_native(thread);
|
||||
if (native_thread != NULL) {
|
||||
JfrThreadLocal::exclude(native_thread);
|
||||
} else {
|
||||
@ -744,10 +746,7 @@ void JfrJavaSupport::exclude(jobject thread) {
|
||||
}
|
||||
|
||||
void JfrJavaSupport::include(jobject thread) {
|
||||
HandleMark hm;
|
||||
ThreadsListHandle tlh;
|
||||
JavaThread* native_thread = NULL;
|
||||
(void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL);
|
||||
JavaThread* native_thread = get_native(thread);
|
||||
if (native_thread != NULL) {
|
||||
JfrThreadLocal::include(native_thread);
|
||||
} else {
|
||||
@ -757,10 +756,7 @@ void JfrJavaSupport::include(jobject thread) {
|
||||
}
|
||||
|
||||
bool JfrJavaSupport::is_excluded(jobject thread) {
|
||||
HandleMark hm;
|
||||
ThreadsListHandle tlh;
|
||||
JavaThread* native_thread = NULL;
|
||||
(void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL);
|
||||
JavaThread* native_thread = get_native(thread);
|
||||
return native_thread != NULL ? native_thread->jfr_thread_local()->is_excluded() : is_thread_excluded(thread);
|
||||
}
|
||||
|
||||
|
@ -179,6 +179,12 @@ NO_TRANSITION(jboolean, jfr_should_rotate_disk(JNIEnv* env, jobject jvm))
|
||||
return JfrChunkRotation::should_rotate() ? JNI_TRUE : JNI_FALSE;
|
||||
NO_TRANSITION_END
|
||||
|
||||
NO_TRANSITION(jlong, jfr_get_type_id_from_string(JNIEnv * env, jobject jvm, jstring type))
|
||||
const char* type_name = env->GetStringUTFChars(type, NULL);
|
||||
jlong id = JfrType::name_to_id(type_name);
|
||||
env->ReleaseStringUTFChars(type, type_name);
|
||||
return id;
|
||||
NO_TRANSITION_END
|
||||
/*
|
||||
* JVM_ENTRY_NO_ENV entries
|
||||
*
|
||||
@ -350,11 +356,3 @@ JVM_END
|
||||
JVM_ENTRY_NO_ENV(jboolean, jfr_set_handler(JNIEnv * env, jobject jvm, jobject clazz, jobject handler))
|
||||
return JfrJavaSupport::set_handler(clazz, handler, thread);
|
||||
JVM_END
|
||||
|
||||
NO_TRANSITION(jlong, jfr_get_type_id_from_string(JNIEnv * env, jobject jvm, jstring type))
|
||||
const char* type_name= env->GetStringUTFChars(type, NULL);
|
||||
jlong id = JfrType::name_to_id(type_name);
|
||||
env->ReleaseStringUTFChars(type, type_name);
|
||||
return id;
|
||||
NO_TRANSITION_END
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "jfr/jni/jfrJavaSupport.hpp"
|
||||
#include "jfr/leakprofiler/chains/edgeStore.hpp"
|
||||
#include "jfr/leakprofiler/chains/objectSampleMarker.hpp"
|
||||
#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
|
||||
@ -40,10 +41,12 @@
|
||||
#include "jfr/utilities/jfrHashtable.hpp"
|
||||
#include "jfr/utilities/jfrPredicate.hpp"
|
||||
#include "jfr/utilities/jfrRelation.hpp"
|
||||
#include "memory/resourceArea.inline.hpp"
|
||||
#include "oops/instanceKlass.inline.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
|
||||
const int initial_array_size = 64;
|
||||
|
||||
@ -248,17 +251,21 @@ static void install_stack_traces(const ObjectSampler* sampler, JfrStackTraceRepo
|
||||
assert(sampler != NULL, "invariant");
|
||||
const ObjectSample* const last = sampler->last();
|
||||
if (last != sampler->last_resolved()) {
|
||||
ResourceMark rm;
|
||||
JfrKlassUnloading::sort();
|
||||
StackTraceBlobInstaller installer(stack_trace_repo);
|
||||
iterate_samples(installer);
|
||||
}
|
||||
}
|
||||
|
||||
// caller needs ResourceMark
|
||||
void ObjectSampleCheckpoint::on_rotation(const ObjectSampler* sampler, JfrStackTraceRepository& stack_trace_repo) {
|
||||
assert(JfrStream_lock->owned_by_self(), "invariant");
|
||||
assert(sampler != NULL, "invariant");
|
||||
assert(LeakProfiler::is_running(), "invariant");
|
||||
Thread* const thread = Thread::current();
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(thread);)
|
||||
// can safepoint here
|
||||
ThreadInVMfromNative transition((JavaThread*)thread);
|
||||
MutexLocker lock(ClassLoaderDataGraph_lock);
|
||||
// the lock is needed to ensure the unload lists do not grow in the middle of inspection.
|
||||
install_stack_traces(sampler, stack_trace_repo);
|
||||
@ -416,6 +423,7 @@ static void save_type_set_blob(JfrCheckpointWriter& writer, bool copy = false) {
|
||||
|
||||
void ObjectSampleCheckpoint::on_type_set(JfrCheckpointWriter& writer) {
|
||||
assert(LeakProfiler::is_running(), "invariant");
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(Thread::current());)
|
||||
const ObjectSample* last = ObjectSampler::sampler()->last();
|
||||
if (writer.has_data() && last != NULL) {
|
||||
save_type_set_blob(writer);
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "jfr/jni/jfrJavaSupport.hpp"
|
||||
#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
|
||||
#include "jfr/leakprofiler/leakProfiler.hpp"
|
||||
#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
|
||||
@ -48,6 +49,7 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/mutex.hpp"
|
||||
#include "runtime/os.inline.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
@ -325,6 +327,7 @@ void JfrCheckpointManager::end_epoch_shift() {
|
||||
}
|
||||
|
||||
size_t JfrCheckpointManager::write() {
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(Thread::current()));
|
||||
assert(_mspace->free_list_is_empty(), "invariant");
|
||||
WriteOperation wo(_chunkwriter);
|
||||
MutexedWriteOperation mwo(wo);
|
||||
@ -357,6 +360,11 @@ size_t JfrCheckpointManager::write_static_type_set(Thread* thread) {
|
||||
|
||||
size_t JfrCheckpointManager::write_threads(Thread* thread) {
|
||||
assert(thread != NULL, "invariant");
|
||||
// can safepoint here
|
||||
ThreadInVMfromNative transition((JavaThread*)thread);
|
||||
ResetNoHandleMark rnhm;
|
||||
ResourceMark rm(thread);
|
||||
HandleMark hm(thread);
|
||||
JfrCheckpointWriter writer(true, thread, THREADS);
|
||||
JfrTypeManager::write_threads(writer);
|
||||
return writer.used_size();
|
||||
@ -364,8 +372,7 @@ size_t JfrCheckpointManager::write_threads(Thread* thread) {
|
||||
|
||||
size_t JfrCheckpointManager::write_static_type_set_and_threads() {
|
||||
Thread* const thread = Thread::current();
|
||||
ResourceMark rm(thread);
|
||||
HandleMark hm(thread);
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(thread));
|
||||
write_static_type_set(thread);
|
||||
write_threads(thread);
|
||||
return write();
|
||||
@ -380,7 +387,11 @@ void JfrCheckpointManager::on_rotation() {
|
||||
void JfrCheckpointManager::clear_type_set() {
|
||||
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
|
||||
assert(!JfrRecorder::is_recording(), "invariant");
|
||||
Thread* t = Thread::current();
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(t));
|
||||
// can safepoint here
|
||||
ThreadInVMfromNative transition((JavaThread*)t);
|
||||
ResetNoHandleMark rnhm;
|
||||
MutexLocker cld_lock(ClassLoaderDataGraph_lock);
|
||||
MutexLocker module_lock(Module_lock);
|
||||
JfrTypeSet::clear();
|
||||
@ -388,21 +399,23 @@ void JfrCheckpointManager::clear_type_set() {
|
||||
|
||||
void JfrCheckpointManager::write_type_set() {
|
||||
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
|
||||
Thread* const thread = Thread::current();
|
||||
if (LeakProfiler::is_running()) {
|
||||
{
|
||||
Thread* const thread = Thread::current();
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(thread));
|
||||
// can safepoint here
|
||||
ThreadInVMfromNative transition((JavaThread*)thread);
|
||||
ResetNoHandleMark rnhm;
|
||||
MutexLocker cld_lock(thread, ClassLoaderDataGraph_lock);
|
||||
MutexLocker module_lock(thread, Module_lock);
|
||||
JfrCheckpointWriter leakp_writer(true, thread);
|
||||
JfrCheckpointWriter writer(true, thread);
|
||||
JfrTypeSet::serialize(&writer, &leakp_writer, false, false);
|
||||
ObjectSampleCheckpoint::on_type_set(leakp_writer);
|
||||
} else {
|
||||
// can safepoint here
|
||||
MutexLocker cld_lock(ClassLoaderDataGraph_lock);
|
||||
MutexLocker module_lock(Module_lock);
|
||||
JfrCheckpointWriter writer(true, thread);
|
||||
JfrTypeSet::serialize(&writer, NULL, false, false);
|
||||
if (LeakProfiler::is_running()) {
|
||||
JfrCheckpointWriter leakp_writer(true, thread);
|
||||
JfrCheckpointWriter writer(true, thread);
|
||||
JfrTypeSet::serialize(&writer, &leakp_writer, false, false);
|
||||
ObjectSampleCheckpoint::on_type_set(leakp_writer);
|
||||
} else {
|
||||
JfrCheckpointWriter writer(true, thread);
|
||||
JfrTypeSet::serialize(&writer, NULL, false, false);
|
||||
}
|
||||
}
|
||||
write();
|
||||
}
|
||||
@ -416,13 +429,33 @@ void JfrCheckpointManager::on_unloading_classes() {
|
||||
}
|
||||
}
|
||||
|
||||
class JavaThreadToVM : public StackObj {
|
||||
private:
|
||||
JavaThread* _jt;
|
||||
public:
|
||||
JavaThreadToVM(Thread* thread) : _jt(thread->is_Java_thread() ? (JavaThread*)thread : NULL) {
|
||||
if (_jt != NULL) {
|
||||
assert(_jt->thread_state() == _thread_in_native, "invariant");
|
||||
_jt->set_thread_state(_thread_in_vm);
|
||||
}
|
||||
}
|
||||
~JavaThreadToVM() {
|
||||
if (_jt != NULL) {
|
||||
_jt->set_thread_state(_thread_in_native);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
size_t JfrCheckpointManager::flush_type_set() {
|
||||
size_t elements = 0;
|
||||
if (JfrTraceIdEpoch::has_changed_tag_state()) {
|
||||
JfrCheckpointWriter writer(Thread::current());
|
||||
// can safepoint here
|
||||
MutexLocker cld_lock(ClassLoaderDataGraph_lock);
|
||||
MutexLocker module_lock(Module_lock);
|
||||
Thread* const t = Thread::current();
|
||||
// can safepoint here (if JavaThread)
|
||||
JavaThreadToVM transition(t);
|
||||
ResetNoHandleMark rnhm;
|
||||
MutexLocker cld_lock(t, ClassLoaderDataGraph_lock);
|
||||
MutexLocker module_lock(t, Module_lock);
|
||||
JfrCheckpointWriter writer(t);
|
||||
elements = JfrTypeSet::serialize(&writer, NULL, false, true);
|
||||
}
|
||||
if (is_constant_pending()) {
|
||||
|
@ -29,14 +29,18 @@
|
||||
#include "oops/klass.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "oops/typeArrayOop.inline.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
|
||||
static jbyteArray metadata_blob = NULL;
|
||||
static u8 metadata_id = 0;
|
||||
static u8 last_metadata_id = 0;
|
||||
|
||||
static void write_metadata_blob(JfrChunkWriter& chunkwriter) {
|
||||
static void write_metadata_blob(JfrChunkWriter& chunkwriter, Thread* thread) {
|
||||
assert(chunkwriter.is_valid(), "invariant");
|
||||
assert(thread != NULL, "invariant");
|
||||
assert(metadata_blob != NULL, "invariant");
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
|
||||
const typeArrayOop arr = (typeArrayOop)JfrJavaSupport::resolve_non_null(metadata_blob);
|
||||
assert(arr != NULL, "invariant");
|
||||
const int length = arr->length();
|
||||
@ -47,11 +51,15 @@ static void write_metadata_blob(JfrChunkWriter& chunkwriter) {
|
||||
chunkwriter.write_unbuffered(data_address, length);
|
||||
}
|
||||
|
||||
bool JfrMetadataEvent::write(JfrChunkWriter& chunkwriter) {
|
||||
void JfrMetadataEvent::write(JfrChunkWriter& chunkwriter) {
|
||||
assert(chunkwriter.is_valid(), "invariant");
|
||||
if (last_metadata_id == metadata_id && chunkwriter.has_metadata()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
JavaThread* const jt = (JavaThread*)Thread::current();
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
|
||||
// can safepoint here
|
||||
ThreadInVMfromNative transition(jt);
|
||||
// header
|
||||
const int64_t metadata_offset = chunkwriter.reserve(sizeof(u4));
|
||||
chunkwriter.write<u8>(EVENT_METADATA); // ID 0
|
||||
@ -59,13 +67,12 @@ bool JfrMetadataEvent::write(JfrChunkWriter& chunkwriter) {
|
||||
chunkwriter.write(JfrTicks::now());
|
||||
chunkwriter.write((u8)0); // duration
|
||||
chunkwriter.write(metadata_id); // metadata id
|
||||
write_metadata_blob(chunkwriter); // payload
|
||||
write_metadata_blob(chunkwriter, jt); // payload
|
||||
// fill in size of metadata descriptor event
|
||||
const int64_t size_written = chunkwriter.current_offset() - metadata_offset;
|
||||
chunkwriter.write_padded_at_offset((u4)size_written, metadata_offset);
|
||||
chunkwriter.set_last_metadata_offset(metadata_offset);
|
||||
last_metadata_id = metadata_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
void JfrMetadataEvent::update(jbyteArray metadata) {
|
||||
|
@ -36,7 +36,7 @@ class JfrChunkWriter;
|
||||
//
|
||||
class JfrMetadataEvent : AllStatic {
|
||||
public:
|
||||
static bool write(JfrChunkWriter& writer);
|
||||
static void write(JfrChunkWriter& writer);
|
||||
static void update(jbyteArray metadata);
|
||||
};
|
||||
|
||||
|
@ -1038,6 +1038,7 @@ size_t JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* l
|
||||
* Clear all tags from the previous epoch.
|
||||
*/
|
||||
void JfrTypeSet::clear() {
|
||||
ResourceMark rm;
|
||||
JfrKlassUnloading::clear();
|
||||
clear_artifacts = true;
|
||||
setup(NULL, NULL, false, false);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
@ -27,6 +27,7 @@
|
||||
#include "jfr/recorder/repository/jfrChunkRotation.hpp"
|
||||
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
|
||||
static jobject chunk_monitor = NULL;
|
||||
static int64_t threshold = 0;
|
||||
@ -53,6 +54,9 @@ static jobject get_chunk_monitor(Thread* thread) {
|
||||
|
||||
static void notify() {
|
||||
Thread* const thread = Thread::current();
|
||||
// can safepoint here
|
||||
ThreadInVMfromNative transition((JavaThread*)thread);
|
||||
ResetNoHandleMark rnhm;
|
||||
JfrJavaSupport::notify_all(get_chunk_monitor(thread), thread);
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
@ -422,7 +423,7 @@ const char* JfrEmergencyDump::chunk_path(const char* repository_path) {
|
||||
*/
|
||||
static bool prepare_for_emergency_dump(Thread* thread) {
|
||||
assert(thread != NULL, "invariant");
|
||||
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
|
||||
if (thread->is_Watcher_thread()) {
|
||||
// need WatcherThread as a safeguard against potential deadlocks
|
||||
return false;
|
||||
@ -501,29 +502,38 @@ static bool guard_reentrancy() {
|
||||
return Atomic::cmpxchg(&jfr_shutdown_lock, 0, 1) == 0;
|
||||
}
|
||||
|
||||
class JavaThreadInVM : public StackObj {
|
||||
class JavaThreadInVMAndNative : public StackObj {
|
||||
private:
|
||||
JavaThread* const _jt;
|
||||
JavaThreadState _original_state;
|
||||
public:
|
||||
|
||||
JavaThreadInVM(Thread* t) : _jt(t->is_Java_thread() ? (JavaThread*)t : NULL),
|
||||
_original_state(_thread_max_state) {
|
||||
if ((_jt != NULL) && (_jt->thread_state() != _thread_in_vm)) {
|
||||
JavaThreadInVMAndNative(Thread* t) : _jt(t->is_Java_thread() ? (JavaThread*)t : NULL),
|
||||
_original_state(_thread_max_state) {
|
||||
if (_jt != NULL) {
|
||||
_original_state = _jt->thread_state();
|
||||
_jt->set_thread_state(_thread_in_vm);
|
||||
if (_original_state != _thread_in_vm) {
|
||||
_jt->set_thread_state(_thread_in_vm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~JavaThreadInVM() {
|
||||
~JavaThreadInVMAndNative() {
|
||||
if (_original_state != _thread_max_state) {
|
||||
_jt->set_thread_state(_original_state);
|
||||
}
|
||||
}
|
||||
|
||||
void transition_to_native() {
|
||||
if (_jt != NULL) {
|
||||
assert(_jt->thread_state() == _thread_in_vm, "invariant");
|
||||
_jt->set_thread_state(_thread_in_native);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void post_events(bool exception_handler) {
|
||||
static void post_events(bool exception_handler, Thread* thread) {
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
|
||||
if (exception_handler) {
|
||||
EventShutdown e;
|
||||
e.set_reason("VM Error");
|
||||
@ -547,11 +557,14 @@ void JfrEmergencyDump::on_vm_shutdown(bool exception_handler) {
|
||||
return;
|
||||
}
|
||||
// Ensure a JavaThread is _thread_in_vm when we make this call
|
||||
JavaThreadInVM jtivm(thread);
|
||||
JavaThreadInVMAndNative jtivm(thread);
|
||||
if (!prepare_for_emergency_dump(thread)) {
|
||||
return;
|
||||
}
|
||||
post_events(exception_handler);
|
||||
post_events(exception_handler, thread);
|
||||
// if JavaThread, transition to _thread_in_native to issue a final flushpoint
|
||||
NoHandleMark nhm;
|
||||
jtivm.transition_to_native();
|
||||
const int messages = MSGBIT(MSG_VM_ERROR);
|
||||
JfrRecorderService service;
|
||||
service.rotate(messages);
|
||||
|
@ -45,9 +45,8 @@
|
||||
#include "jfr/writers/jfrJavaEventWriter.hpp"
|
||||
#include "jfr/utilities/jfrTypes.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
@ -373,8 +372,6 @@ static void stop() {
|
||||
}
|
||||
|
||||
void JfrRecorderService::clear() {
|
||||
ResourceMark rm;
|
||||
HandleMark hm;
|
||||
pre_safepoint_clear();
|
||||
invoke_safepoint_clear();
|
||||
post_safepoint_clear();
|
||||
@ -388,6 +385,7 @@ void JfrRecorderService::pre_safepoint_clear() {
|
||||
|
||||
void JfrRecorderService::invoke_safepoint_clear() {
|
||||
JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_clear> safepoint_task(*this);
|
||||
ThreadInVMfromNative transition((JavaThread*)Thread::current());
|
||||
VMThread::execute(&safepoint_task);
|
||||
}
|
||||
|
||||
@ -474,6 +472,7 @@ void JfrRecorderService::vm_error_rotation() {
|
||||
|
||||
void JfrRecorderService::rotate(int msgs) {
|
||||
assert(!JfrStream_lock->owned_by_self(), "invariant");
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(Thread::current()));
|
||||
if (msgs & MSGBIT(MSG_VM_ERROR)) {
|
||||
// emergency dump
|
||||
if (!prepare_for_vm_error_rotation()) {
|
||||
@ -521,8 +520,6 @@ void JfrRecorderService::finalize_current_chunk() {
|
||||
}
|
||||
|
||||
void JfrRecorderService::write() {
|
||||
ResourceMark rm;
|
||||
HandleMark hm;
|
||||
pre_safepoint_write();
|
||||
invoke_safepoint_write();
|
||||
post_safepoint_write();
|
||||
@ -547,6 +544,8 @@ void JfrRecorderService::pre_safepoint_write() {
|
||||
|
||||
void JfrRecorderService::invoke_safepoint_write() {
|
||||
JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this);
|
||||
// can safepoint here
|
||||
ThreadInVMfromNative transition((JavaThread*)Thread::current());
|
||||
VMThread::execute(&safepoint_task);
|
||||
}
|
||||
|
||||
@ -632,8 +631,6 @@ void JfrRecorderService::invoke_flush() {
|
||||
assert(JfrStream_lock->owned_by_self(), "invariant");
|
||||
assert(_chunkwriter.is_valid(), "invariant");
|
||||
Thread* const t = Thread::current();
|
||||
ResourceMark rm(t);
|
||||
HandleMark hm(t);
|
||||
++flushpoint_id;
|
||||
reset_thread_local_buffer(t);
|
||||
FlushFunctor flushpoint(*this);
|
||||
@ -644,6 +641,7 @@ void JfrRecorderService::invoke_flush() {
|
||||
}
|
||||
|
||||
void JfrRecorderService::flushpoint() {
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(Thread::current()));
|
||||
MutexLocker lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
|
||||
if (_chunkwriter.is_valid()) {
|
||||
invoke_flush();
|
||||
@ -651,11 +649,13 @@ void JfrRecorderService::flushpoint() {
|
||||
}
|
||||
|
||||
void JfrRecorderService::process_full_buffers() {
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(Thread::current()));
|
||||
if (_chunkwriter.is_valid()) {
|
||||
_storage.write_full();
|
||||
}
|
||||
}
|
||||
|
||||
void JfrRecorderService::evaluate_chunk_size_for_rotation() {
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(Thread::current()));
|
||||
JfrChunkRotation::evaluate(_chunkwriter);
|
||||
}
|
||||
|
@ -23,11 +23,15 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "jfr/jni/jfrJavaSupport.hpp"
|
||||
#include "jfr/recorder/jfrRecorder.hpp"
|
||||
#include "jfr/recorder/service/jfrPostBox.hpp"
|
||||
#include "jfr/recorder/service/jfrRecorderService.hpp"
|
||||
#include "jfr/recorder/service/jfrRecorderThread.hpp"
|
||||
#include "jfr/recorder/jfrRecorder.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/handles.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
|
||||
@ -59,18 +63,24 @@ void recorderthread_entry(JavaThread* thread, Thread* unused) {
|
||||
}
|
||||
msgs = post_box.collect();
|
||||
JfrMsg_lock->unlock();
|
||||
if (PROCESS_FULL_BUFFERS) {
|
||||
service.process_full_buffers();
|
||||
}
|
||||
// Check amount of data written to chunk already
|
||||
// if it warrants asking for a new chunk
|
||||
service.evaluate_chunk_size_for_rotation();
|
||||
if (START) {
|
||||
service.start();
|
||||
} else if (ROTATE) {
|
||||
service.rotate(msgs);
|
||||
} else if (FLUSHPOINT) {
|
||||
service.flushpoint();
|
||||
{
|
||||
// Run as _thread_in_native as much a possible
|
||||
// to minimize impact on safepoint synchronizations.
|
||||
NoHandleMark nhm;
|
||||
ThreadToNativeFromVM transition(thread);
|
||||
if (PROCESS_FULL_BUFFERS) {
|
||||
service.process_full_buffers();
|
||||
}
|
||||
// Check amount of data written to chunk already
|
||||
// if it warrants asking for a new chunk.
|
||||
service.evaluate_chunk_size_for_rotation();
|
||||
if (START) {
|
||||
service.start();
|
||||
} else if (ROTATE) {
|
||||
service.rotate(msgs);
|
||||
} else if (FLUSHPOINT) {
|
||||
service.flushpoint();
|
||||
}
|
||||
}
|
||||
JfrMsg_lock->lock();
|
||||
post_box.notify_waiters();
|
||||
|
@ -65,11 +65,11 @@
|
||||
*
|
||||
* We say that the FIFO solution is "mostly" concurrent, in certain situations.
|
||||
*
|
||||
* Safe memory reclamation is based on a reference tracking scheme based on versions, implemented using JfrVersion.
|
||||
* An access to the list is "version controlled", with clients checking out the latest version of the list.
|
||||
* Destructive modifications made by clients, i.e. deletions, are committed to describe new versions of the list.
|
||||
* Before reclamation, a client inspects the versioning system to ensure checkouts for versions strictly
|
||||
* less than the version of the modification have all been relinquished. See utilities/JfrVersion.hpp.
|
||||
* Safe memory reclamation is based on a reference tracking scheme based on versioning, implemented using JfrVersionSystem.
|
||||
* An access to the list is "versioned", with clients checking out the latest version describing the list.
|
||||
* Destructive modifications made by clients, i.e. deletions, are signalled by incrementing the version.
|
||||
* Before reclamation, a client inspects JfrVersionSystem to ensure checkouts with versions strictly
|
||||
* less than the version of the modification have been relinquished. See utilities/JfrVersionSystem.hpp.
|
||||
*
|
||||
* Insertions can only take place from one end of the list, head or tail, exclusively.
|
||||
* Specializations, a.k.a clients, must ensure this requirement.
|
||||
|
@ -222,7 +222,7 @@ typename Client::Node* JfrConcurrentLinkedListHost<Client, SearchPolicy, AllocPo
|
||||
assert(is_marked_for_removal(successor->_next), "invariant");
|
||||
// Now attempt to physically excise the successor node.
|
||||
// If the cas fails, we can optimize for the slow path if we know we are not performing
|
||||
// insertions from the head. Then a failed cas results not from new a node being inserted,
|
||||
// insertions from the head. Then a failed cas results not from a new node being inserted,
|
||||
// but only because another thread excised us already.
|
||||
if (!cas(&predecessor->_next, successor, successor_next) && insert_is_head) {
|
||||
// Physically excise using slow path, can be completed asynchronously by other threads.
|
||||
|
@ -25,11 +25,9 @@
|
||||
#ifndef SHARE_JFR_UTILITIES_JFRVERSIONSYSTEM_INLINE_HPP
|
||||
#define SHARE_JFR_UTILITIES_JFRVERSIONSYSTEM_INLINE_HPP
|
||||
|
||||
#include "jfr/utilities/jfrSpinlockHelper.hpp"
|
||||
#include "jfr/utilities/jfrVersionSystem.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/os.inline.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
|
||||
inline JfrVersionSystem::Node::Node() : _next(NULL), _version(0), _live(true) {}
|
||||
|
||||
@ -65,10 +63,6 @@ inline JfrVersionSystem::Type JfrVersionSystem::tip() const {
|
||||
}
|
||||
|
||||
inline JfrVersionSystem::Type JfrVersionSystem::increment() {
|
||||
if (!VM_Version::supports_cx8()) {
|
||||
JfrSpinlockHelper lock(&_spinlock);
|
||||
return ++_tip._value;
|
||||
}
|
||||
traceid cmp;
|
||||
traceid xchg;
|
||||
do {
|
||||
|
Loading…
x
Reference in New Issue
Block a user