8338417: Explicitly pin a virtual thread before acquiring the JFR string pool monitor

Reviewed-by: alanb, egahlin, dholmes
This commit is contained in:
Markus Grönlund 2024-08-23 09:29:23 +00:00
parent fead3cf541
commit 69bd227e6c
6 changed files with 217 additions and 38 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024, 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
@ -36,6 +36,7 @@
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/globals.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/jniHandles.inline.hpp"
@ -49,6 +50,7 @@ static int max_pos_offset = invalid_offset;
static int excluded_offset = invalid_offset;
static int thread_id_offset = invalid_offset;
static int valid_offset = invalid_offset;
static int pin_offset = invalid_offset;
static bool setup_event_writer_offsets(TRAPS) {
const char class_name[] = "jdk/jfr/internal/event/EventWriter";
@ -98,6 +100,13 @@ static bool setup_event_writer_offsets(TRAPS) {
assert(invalid_offset == valid_offset, "invariant");
JfrJavaSupport::compute_field_offset(valid_offset, klass, valid_sym, vmSymbols::bool_signature());
assert(valid_offset != invalid_offset, "invariant");
const char pin_name[] = "pinVirtualThread";
Symbol* const pin_sym = SymbolTable::new_symbol(valid_name);
assert(pin_sym != nullptr, "invariant");
assert(invalid_offset == pin_offset, "invariant");
JfrJavaSupport::compute_field_offset(pin_offset, klass, pin_sym, vmSymbols::bool_signature());
assert(pin_offset != invalid_offset, "invariant");
return true;
}
@ -219,13 +228,18 @@ void JfrJavaEventWriter::notify(JavaThread* jt) {
}
}
static inline bool pin_virtual(const JavaThread* jt) {
assert(jt != nullptr, "invariant");
return JfrThreadLocal::is_vthread(jt) && VMContinuations;
}
static jobject create_new_event_writer(JfrBuffer* buffer, JfrThreadLocal* tl, TRAPS) {
assert(buffer != nullptr, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
HandleMark hm(THREAD);
static const char klass[] = "jdk/jfr/internal/event/EventWriter";
static const char method[] = "<init>";
static const char signature[] = "(JJJZZ)V";
static const char signature[] = "(JJJZZZ)V";
JavaValue result(T_OBJECT);
JfrJavaArguments args(&result, klass, method, signature, CHECK_NULL);
@ -234,6 +248,7 @@ static jobject create_new_event_writer(JfrBuffer* buffer, JfrThreadLocal* tl, TR
args.push_long((jlong)buffer->end());
args.push_long((jlong)JfrThreadLocal::thread_id(THREAD));
args.push_int((jint)JNI_TRUE); // valid
args.push_int(pin_virtual(THREAD) ? (jint)JNI_TRUE : (jint)JNI_FALSE);
args.push_int(tl->is_excluded() ? (jint)JNI_TRUE : (jint)JNI_FALSE); // excluded
JfrJavaSupport::new_object_global_ref(&args, CHECK_NULL);
return result.get_jobject();
@ -249,9 +264,12 @@ jobject JfrJavaEventWriter::event_writer(JavaThread* jt) {
const jlong event_writer_tid = writer->long_field(thread_id_offset);
const jlong current_tid = static_cast<jlong>(JfrThreadLocal::thread_id(jt));
if (event_writer_tid != current_tid) {
writer->long_field_put(thread_id_offset, current_tid);
const bool excluded = tl->is_excluded();
writer->bool_field_put(excluded_offset, excluded);
writer->long_field_put(thread_id_offset, current_tid);
if (!excluded) {
writer->bool_field_put(pin_offset, pin_virtual(jt));
}
}
}
return h_writer;