mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8167108: inconsistent handling of SR_lock can lead to crashes
Add Thread Safe Memory Reclamation (Thread-SMR) mechanism. Co-authored-by: Erik Osterlund <erik.osterlund@oracle.com> Co-authored-by: Robbin Ehn <robbin.ehn@oracle.com> Reviewed-by: coleenp, dcubed, dholmes, eosterlund, gthornbr, kbarrett, rehn, sspitsyn, stefank
This commit is contained in:
parent
cd0c6d0fae
commit
0dff96ff0b
67 changed files with 4220 additions and 995 deletions
|
@ -53,6 +53,7 @@
|
|||
#include "runtime/objectMonitor.inline.hpp"
|
||||
#include "runtime/os.inline.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
#include "runtime/threadSMR.hpp"
|
||||
#include "runtime/vframe.hpp"
|
||||
#include "services/serviceUtil.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
@ -721,6 +722,108 @@ JvmtiExport::get_all_native_method_prefixes(int* count_ptr) {
|
|||
}
|
||||
}
|
||||
|
||||
// Convert an external thread reference to a JavaThread found on the
|
||||
// specified ThreadsList. The ThreadsListHandle in the caller "protects"
|
||||
// the returned JavaThread *.
|
||||
//
|
||||
// If thread_oop_p is not NULL, then the caller wants to use the oop
|
||||
// after this call so the oop is returned. On success, *jt_pp is set
|
||||
// to the converted JavaThread * and JVMTI_ERROR_NONE is returned.
|
||||
// On error, returns various JVMTI_ERROR_* values.
|
||||
//
|
||||
jvmtiError
|
||||
JvmtiExport::cv_external_thread_to_JavaThread(ThreadsList * t_list,
|
||||
jthread thread,
|
||||
JavaThread ** jt_pp,
|
||||
oop * thread_oop_p) {
|
||||
assert(t_list != NULL, "must have a ThreadsList");
|
||||
assert(jt_pp != NULL, "must have a return JavaThread pointer");
|
||||
// thread_oop_p is optional so no assert()
|
||||
|
||||
oop thread_oop = JNIHandles::resolve_external_guard(thread);
|
||||
if (thread_oop == NULL) {
|
||||
// NULL jthread, GC'ed jthread or a bad JNI handle.
|
||||
return JVMTI_ERROR_INVALID_THREAD;
|
||||
}
|
||||
// Looks like an oop at this point.
|
||||
|
||||
if (!thread_oop->is_a(SystemDictionary::Thread_klass())) {
|
||||
// The oop is not a java.lang.Thread.
|
||||
return JVMTI_ERROR_INVALID_THREAD;
|
||||
}
|
||||
// Looks like a java.lang.Thread oop at this point.
|
||||
|
||||
if (thread_oop_p != NULL) {
|
||||
// Return the oop to the caller; the caller may still want
|
||||
// the oop even if this function returns an error.
|
||||
*thread_oop_p = thread_oop;
|
||||
}
|
||||
|
||||
JavaThread * java_thread = java_lang_Thread::thread(thread_oop);
|
||||
if (java_thread == NULL) {
|
||||
// The java.lang.Thread does not contain a JavaThread * so it has
|
||||
// not yet run or it has died.
|
||||
return JVMTI_ERROR_THREAD_NOT_ALIVE;
|
||||
}
|
||||
// Looks like a live JavaThread at this point.
|
||||
|
||||
// We do not check the EnableThreadSMRExtraValidityChecks option
|
||||
// for this includes() call because JVM/TI's spec is tighter.
|
||||
if (!t_list->includes(java_thread)) {
|
||||
// Not on the JavaThreads list so it is not alive.
|
||||
return JVMTI_ERROR_THREAD_NOT_ALIVE;
|
||||
}
|
||||
|
||||
// Return a live JavaThread that is "protected" by the
|
||||
// ThreadsListHandle in the caller.
|
||||
*jt_pp = java_thread;
|
||||
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
// Convert an oop to a JavaThread found on the specified ThreadsList.
|
||||
// The ThreadsListHandle in the caller "protects" the returned
|
||||
// JavaThread *.
|
||||
//
|
||||
// On success, *jt_pp is set to the converted JavaThread * and
|
||||
// JVMTI_ERROR_NONE is returned. On error, returns various
|
||||
// JVMTI_ERROR_* values.
|
||||
//
|
||||
jvmtiError
|
||||
JvmtiExport::cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop,
|
||||
JavaThread ** jt_pp) {
|
||||
assert(t_list != NULL, "must have a ThreadsList");
|
||||
assert(thread_oop != NULL, "must have an oop");
|
||||
assert(jt_pp != NULL, "must have a return JavaThread pointer");
|
||||
|
||||
if (!thread_oop->is_a(SystemDictionary::Thread_klass())) {
|
||||
// The oop is not a java.lang.Thread.
|
||||
return JVMTI_ERROR_INVALID_THREAD;
|
||||
}
|
||||
// Looks like a java.lang.Thread oop at this point.
|
||||
|
||||
JavaThread * java_thread = java_lang_Thread::thread(thread_oop);
|
||||
if (java_thread == NULL) {
|
||||
// The java.lang.Thread does not contain a JavaThread * so it has
|
||||
// not yet run or it has died.
|
||||
return JVMTI_ERROR_THREAD_NOT_ALIVE;
|
||||
}
|
||||
// Looks like a live JavaThread at this point.
|
||||
|
||||
// We do not check the EnableThreadSMRExtraValidityChecks option
|
||||
// for this includes() call because JVM/TI's spec is tighter.
|
||||
if (!t_list->includes(java_thread)) {
|
||||
// Not on the JavaThreads list so it is not alive.
|
||||
return JVMTI_ERROR_THREAD_NOT_ALIVE;
|
||||
}
|
||||
|
||||
// Return a live JavaThread that is "protected" by the
|
||||
// ThreadsListHandle in the caller.
|
||||
*jt_pp = java_thread;
|
||||
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
class JvmtiClassFileLoadHookPoster : public StackObj {
|
||||
private:
|
||||
Symbol* _h_name;
|
||||
|
@ -2685,8 +2788,7 @@ void JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(OopClosure* f) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Runs at safepoint. So no need to acquire Threads_lock.
|
||||
for (JavaThread *jthr = Threads::first(); jthr != NULL; jthr = jthr->next()) {
|
||||
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jthr = jtiwh.next(); ) {
|
||||
JvmtiThreadState *state = jthr->jvmti_thread_state();
|
||||
if (state != NULL) {
|
||||
JvmtiVMObjectAllocEventCollector *collector;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue